Changeset View
Changeset View
Standalone View
Standalone View
src/rcu.cpp
Show First 20 Lines • Show All 188 Lines • ▼ Show 20 Lines | void RCUInfos::synchronize() { | ||||
do { | do { | ||||
runCleanups(); | runCleanups(); | ||||
cond.notify_one(); | cond.notify_one(); | ||||
} while (!cond.wait_for(lock, std::chrono::microseconds(1), [&] { | } while (!cond.wait_for(lock, std::chrono::microseconds(1), [&] { | ||||
return cleanups.empty() && hasSyncedTo(syncRev); | return cleanups.empty() && hasSyncedTo(syncRev); | ||||
})); | })); | ||||
} | } | ||||
class RCUInfos::RCUCleanupGuard { | |||||
RCUInfos *infos; | |||||
public: | |||||
explicit RCUCleanupGuard(RCUInfos *infosIn) : infos(infosIn) { | |||||
infos->isCleaningUp = true; | |||||
} | |||||
~RCUCleanupGuard() { infos->isCleaningUp = false; } | |||||
}; | |||||
void RCUInfos::runCleanups() { | void RCUInfos::runCleanups() { | ||||
// By the time we run a set of cleanups, we may have more cleanups | if (isCleaningUp || cleanups.empty()) { | ||||
// available so we loop until there is nothing available for cleanup. | // We don't want to run cleanups within cleanups. | ||||
while (true) { | |||||
if (cleanups.empty()) { | |||||
// There is nothing to cleanup. | |||||
return; | return; | ||||
} | } | ||||
RCUCleanupGuard guard(this); | |||||
// By the time we run a set of cleanups, we may have more cleanups | |||||
// available so we loop until there is nothing available for cleanup. | |||||
while (!cleanups.empty()) { | |||||
auto it = cleanups.begin(); | auto it = cleanups.begin(); | ||||
uint64_t syncedTo = hasSyncedTo(it->first); | uint64_t syncedTo = hasSyncedTo(it->first); | ||||
if (it->first > syncedTo) { | |||||
// We have nothing more ready to be cleaned up. | |||||
return; | |||||
} | |||||
while (it != cleanups.end() && it->first <= syncedTo) { | while (it != cleanups.end() && it->first <= syncedTo) { | ||||
// Run the cleanup and remove it from the map. | // Run the cleanup and remove it from the map. | ||||
it->second(); | auto fun = std::move(it->second); | ||||
cleanups.erase(it++); | cleanups.erase(it++); | ||||
fun(); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
uint64_t RCUInfos::hasSyncedTo(uint64_t cutoff) { | uint64_t RCUInfos::hasSyncedTo(uint64_t cutoff) { | ||||
uint64_t syncedTo = revision.load(); | uint64_t syncedTo = revision.load(); | ||||
// Go over the list and check all threads are past the synchronization | // Go over the list and check all threads are past the synchronization | ||||
Show All 14 Lines |