| 5398 | } |
| 5399 | |
| 5400 | inline BufferDesc* BCBHashTable::emplace(BufferDesc* bdb, const PageNumber& page, bool remove) |
| 5401 | { |
| 5402 | #ifndef HASH_USE_CDS_LIST |
| 5403 | // bcb_syncObject should be locked in EX mode |
| 5404 | |
| 5405 | BufferDesc* bdb2 = find(page); |
| 5406 | if (!bdb2) |
| 5407 | { |
| 5408 | if (remove) |
| 5409 | QUE_DELETE(bdb->bdb_que); |
| 5410 | |
| 5411 | que& mod_que = m_chains[hash(page)]; |
| 5412 | QUE_INSERT(mod_que, bdb->bdb_que); |
| 5413 | } |
| 5414 | return bdb2; |
| 5415 | #else // HASH_USE_CDS_LIST |
| 5416 | |
| 5417 | BufferDesc* bdb2 = nullptr; |
| 5418 | BdbList& list = m_chains[hash(page)]; |
| 5419 | |
| 5420 | /* |
| 5421 | // Original libcds have no update(key, value), use this code with it |
| 5422 | |
| 5423 | auto ret = list.update(page, [bdb, &bdb2](bool bNew, BdbList::value_type& val) |
| 5424 | { |
| 5425 | if (bNew) |
| 5426 | val.second = bdb; |
| 5427 | else |
| 5428 | while (!(bdb2 = val.second)) |
| 5429 | cds::backoff::pause(); |
| 5430 | }, |
| 5431 | true); |
| 5432 | */ |
| 5433 | |
| 5434 | auto ret = list.update(page, bdb, [&bdb2](bool bNew, BdbList::value_type& val) |
| 5435 | { |
| 5436 | // someone might have put a page buffer in the chain concurrently, so |
| 5437 | // we store it for the further investigation |
| 5438 | if (!bNew) |
| 5439 | bdb2 = val.second; |
| 5440 | }, |
| 5441 | true); |
| 5442 | fb_assert(ret.first); |
| 5443 | |
| 5444 | // if we have inserted the page buffer that we found (empty or oldest) |
| 5445 | if (bdb2 == nullptr) |
| 5446 | { |
| 5447 | fb_assert(ret.second); |
| 5448 | #ifdef DEV_BUILD |
| 5449 | auto p1 = list.get(page); |
| 5450 | fb_assert(!p1.empty() && p1->first == page && p1->second == bdb); |
| 5451 | #endif |
| 5452 | |
| 5453 | if (remove) |
| 5454 | { |
| 5455 | // remove the page buffer from old hash slot |
| 5456 | const PageNumber oldPage = bdb->bdb_page; |
| 5457 | BdbList& oldList = m_chains[hash(oldPage)]; |
no test coverage detected