mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-12 08:08:25 +00:00
Small refactor of CCoinsViewCache::BatchWrite()
std::unordered_map::erase( const_iterator pos ) returns an iterator to the element following the removed one. Use that to optimize (probably minor-performance-wise, and definitely code-structure-wise) the implementation of CCoinsViewCache::BatchWrite().
This commit is contained in:
parent
e278f86c53
commit
5b9748f979
@ -146,56 +146,58 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
||||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
|
||||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
|
// Ignore non-dirty entries (optimization).
|
||||||
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
|
if (!(it->second.flags & CCoinsCacheEntry::DIRTY)) {
|
||||||
if (itUs == cacheCoins.end()) {
|
continue;
|
||||||
// The parent cache does not have an entry, while the child does
|
}
|
||||||
// We can ignore it if it's both FRESH and pruned in the child
|
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
|
||||||
if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
|
if (itUs == cacheCoins.end()) {
|
||||||
// Otherwise we will need to create it in the parent
|
// The parent cache does not have an entry, while the child does
|
||||||
// and move the data up and mark it as dirty
|
// We can ignore it if it's both FRESH and pruned in the child
|
||||||
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
|
||||||
entry.coin = std::move(it->second.coin);
|
// Otherwise we will need to create it in the parent
|
||||||
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
|
// and move the data up and mark it as dirty
|
||||||
entry.flags = CCoinsCacheEntry::DIRTY;
|
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
||||||
// We can mark it FRESH in the parent if it was FRESH in the child
|
entry.coin = std::move(it->second.coin);
|
||||||
// Otherwise it might have just been flushed from the parent's cache
|
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
|
||||||
// and already exist in the grandparent
|
entry.flags = CCoinsCacheEntry::DIRTY;
|
||||||
if (it->second.flags & CCoinsCacheEntry::FRESH)
|
// We can mark it FRESH in the parent if it was FRESH in the child
|
||||||
entry.flags |= CCoinsCacheEntry::FRESH;
|
// Otherwise it might have just been flushed from the parent's cache
|
||||||
}
|
// and already exist in the grandparent
|
||||||
} else {
|
if (it->second.flags & CCoinsCacheEntry::FRESH) {
|
||||||
// Assert that the child cache entry was not marked FRESH if the
|
entry.flags |= CCoinsCacheEntry::FRESH;
|
||||||
// parent cache entry has unspent outputs. If this ever happens,
|
|
||||||
// it means the FRESH flag was misapplied and there is a logic
|
|
||||||
// error in the calling code.
|
|
||||||
if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent())
|
|
||||||
throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs");
|
|
||||||
|
|
||||||
// Found the entry in the parent cache
|
|
||||||
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
|
|
||||||
// The grandparent does not have an entry, and the child is
|
|
||||||
// modified and being pruned. This means we can just delete
|
|
||||||
// it from the parent.
|
|
||||||
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
|
|
||||||
cacheCoins.erase(itUs);
|
|
||||||
} else {
|
|
||||||
// A normal modification.
|
|
||||||
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
|
|
||||||
itUs->second.coin = std::move(it->second.coin);
|
|
||||||
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
|
|
||||||
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
|
||||||
// NOTE: It is possible the child has a FRESH flag here in
|
|
||||||
// the event the entry we found in the parent is pruned. But
|
|
||||||
// we must not copy that FRESH flag to the parent as that
|
|
||||||
// pruned state likely still needs to be communicated to the
|
|
||||||
// grandparent.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Assert that the child cache entry was not marked FRESH if the
|
||||||
|
// parent cache entry has unspent outputs. If this ever happens,
|
||||||
|
// it means the FRESH flag was misapplied and there is a logic
|
||||||
|
// error in the calling code.
|
||||||
|
if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) {
|
||||||
|
throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found the entry in the parent cache
|
||||||
|
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
|
||||||
|
// The grandparent does not have an entry, and the child is
|
||||||
|
// modified and being pruned. This means we can just delete
|
||||||
|
// it from the parent.
|
||||||
|
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
|
||||||
|
cacheCoins.erase(itUs);
|
||||||
|
} else {
|
||||||
|
// A normal modification.
|
||||||
|
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
|
||||||
|
itUs->second.coin = std::move(it->second.coin);
|
||||||
|
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
|
||||||
|
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||||
|
// NOTE: It is possible the child has a FRESH flag here in
|
||||||
|
// the event the entry we found in the parent is pruned. But
|
||||||
|
// we must not copy that FRESH flag to the parent as that
|
||||||
|
// pruned state likely still needs to be communicated to the
|
||||||
|
// grandparent.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CCoinsMap::iterator itOld = it++;
|
|
||||||
mapCoins.erase(itOld);
|
|
||||||
}
|
}
|
||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user