diff --git a/ConflictSet.cpp b/ConflictSet.cpp index b3555f0..09bf1b6 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -2510,6 +2510,10 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { } explicit Impl(int64_t oldestVersion) : oldestVersion(oldestVersion) { +#if DEBUG_VERBOSE + fprintf(stderr, "radix_tree: create\n"); +#endif + // Insert "" root = allocators.node0.allocate(0); root->numChildren = 0; @@ -2524,7 +2528,12 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { root->entry.pointVersion = oldestVersion; root->entry.rangeVersion = oldestVersion; } - ~Impl() { destroyTree(root); } + ~Impl() { +#if DEBUG_VERBOSE + fprintf(stderr, "radix_tree: destroy\n"); +#endif + destroyTree(root); + } NodeAllocators allocators; @@ -3005,6 +3014,7 @@ void removeKey(Node *n) { struct __attribute__((visibility("default"))) PeakPrinter { ~PeakPrinter() { + printf("--- radix_tree ---\n"); printf("malloc bytes: %g\n", double(mallocBytes)); printf("Peak malloc bytes: %g\n", double(peakMallocBytes)); printf("Node bytes: %g\n", double(nodeBytes)); diff --git a/SkipList.cpp b/SkipList.cpp index 76e4837..99b002b 100644 --- a/SkipList.cpp +++ b/SkipList.cpp @@ -270,13 +270,21 @@ public: } explicit SkipList(Version version = 0) { +#if DEBUG_VERBOSE + fprintf(stderr, "skip_list: create\n"); +#endif header = Node::create(StringRef(), MaxLevels - 1); for (int l = 0; l < MaxLevels; l++) { header->setNext(l, nullptr); header->setMaxVersion(l, version); } } - ~SkipList() { destroy(); } + ~SkipList() { +#if DEBUG_VERBOSE + fprintf(stderr, "skip_list: destroy\n"); +#endif + destroy(); + } SkipList(SkipList &&other) noexcept : header(other.header) { other.header = nullptr; } @@ -749,6 +757,7 @@ ConflictSet_getBytes(void *cs) { #if SHOW_MEMORY struct __attribute__((visibility("default"))) PeakPrinter { ~PeakPrinter() { + printf("--- skip_list ---\n"); printf("malloc bytes: %g\n", double(mallocBytes)); printf("Peak malloc bytes: %g\n", double(peakMallocBytes)); } diff --git a/conflict_set.py b/conflict_set.py index ccab8c3..54e40d2 100644 --- a/conflict_set.py +++ b/conflict_set.py @@ -134,6 +134,4 @@ class ConflictSet: self.p = None def __exit__(self, exception_type, exception_value, exception_traceback): - if self.p is not None: - self._lib.ConflictSet_destroy(self.p) - self.p = None + self.close() diff --git a/test_conflict_set.py b/test_conflict_set.py index 9e57d87..b324316 100644 --- a/test_conflict_set.py +++ b/test_conflict_set.py @@ -1,8 +1,45 @@ from conflict_set import * +class DebugConflictSet: + """ + Bisimulates the skip list and radix tree conflict sets for testing purposes + """ + + def __init__(self, version: int = 0) -> None: + self.skip_list = ConflictSet(version, implementation="skip_list") + self.radix_tree = ConflictSet(version, implementation="radix_tree") + + def addWrites(self, version: int, *writes: WriteRange): + self.skip_list.addWrites(version, *writes) + self.radix_tree.addWrites(version, *writes) + + def check(self, *reads: ReadRange) -> list[Result]: + expected = self.skip_list.check(*reads) + actual = self.radix_tree.check(*reads) + assert expected == actual + return actual + + def setOldestVersion(self, version: int) -> None: + self.skip_list.setOldestVersion(version) + self.radix_tree.setOldestVersion(version) + + def getBytes(self) -> int: + return self.radix_tree.getBytes() + + def __enter__(self): + return self + + def close(self) -> None: + self.skip_list.close() + self.radix_tree.close() + + def __exit__(self, exception_type, exception_value, exception_traceback): + self.close() + + def test_conflict_set(): - with ConflictSet() as cs: + with DebugConflictSet() as cs: before = cs.getBytes() key = b"a key" cs.addWrites(1, write(key))