diff --git a/RootSet.cpp b/RootSet.cpp index 1b656ac..f70c4b5 100644 --- a/RootSet.cpp +++ b/RootSet.cpp @@ -70,8 +70,14 @@ struct RootSet::Impl { void add(uint32_t node, int64_t version) { ThreadSafeHandle::Impl *h = handle.load(std::memory_order_relaxed); + auto end = h->end.load(std::memory_order_relaxed); + + if (h->roots()[end - 1] == node) { + return; + } + // Upsize if necessary - if (h->end.load(std::memory_order_relaxed) == h->capacity) { + if (end == h->capacity) { h->next = nullptr; auto begin = h->lastLeq(oldestVersion); if (lastToFree != nullptr) { @@ -81,23 +87,20 @@ struct RootSet::Impl { firstToFree = h; lastToFree = h; } - auto *newH = ThreadSafeHandle::Impl::create((h->capacity - begin) * 2); - memcpy(newH->roots(), h->roots() + begin, - sizeof(h->roots()[0]) * (h->capacity - begin)); + auto newEnd = h->capacity - begin; + auto *newH = ThreadSafeHandle::Impl::create(newEnd * 2); + memcpy(newH->roots(), h->roots() + begin, sizeof(h->roots()[0]) * newEnd); memcpy(newH->versions(), h->versions() + begin, - sizeof(h->versions()[0]) * (h->capacity - begin)); - newH->end.store(h->capacity - begin, std::memory_order_relaxed); + sizeof(h->versions()[0]) * newEnd); + newH->end.store(newEnd, std::memory_order_relaxed); handle.store(newH, std::memory_order_release); h = newH; + end = newEnd; } - auto end = h->end.load(std::memory_order_relaxed); - - if (h->roots()[end - 1] != node) { - h->roots()[end] = node; - h->versions()[end] = version; - h->end.store(end + 1, std::memory_order_release); - } + h->roots()[end] = node; + h->versions()[end] = version; + h->end.store(end + 1, std::memory_order_release); } void setOldestVersion(int64_t oldestVersion) {