diff --git a/src/radix.h b/src/radix.h --- a/src/radix.h +++ b/src/radix.h @@ -250,19 +250,16 @@ #undef SEEK_LEAF_LOOP template - void forEachLeaf(RadixElement e, Callable &&func) const { + bool forEachLeaf(RadixElement e, Callable &&func) const { if (e.isNode()) { - e.getNode()->forEachChild( + return e.getNode()->forEachChild( [&](const std::atomic *pElement) { - forEachLeaf(pElement->load(), func); + return forEachLeaf(pElement->load(), func); }); - return; } T *leaf = e.getLeaf(); - if (leaf != nullptr) { - func(RCUPtr::copy(leaf)); - } + return (leaf != nullptr) ? func(RCUPtr::copy(leaf)) : true; } struct RadixElement { @@ -374,10 +371,13 @@ bool isShared() const { return refcount > 0; } - template void forEachChild(Callable &&func) const { + template bool forEachChild(Callable &&func) const { for (size_t i = 0; i < CHILD_PER_LEVEL; i++) { - func(&children[i]); + if (!func(&children[i])) { + return false; + } } + return true; } }; diff --git a/src/test/radix_tests.cpp b/src/test/radix_tests.cpp --- a/src/test/radix_tests.cpp +++ b/src/test/radix_tests.cpp @@ -506,10 +506,25 @@ // This test assumes the key is equal to the value BOOST_CHECK_EQUAL(ptr->getId(), count); BOOST_CHECK_EQUAL(ptr, elements[count++]); + + return true; }); // All the elements are parsed BOOST_CHECK_EQUAL(count, ELEMENTS); + + // Check we can stop the traversal when needed + const size_t stopCount = ELEMENTS / 2; + count = 0; + mytree.forEachLeaf([&](RCUPtr ptr) { + // This test assumes the key is equal to the value + BOOST_CHECK_EQUAL(ptr->getId(), count); + BOOST_CHECK_EQUAL(ptr, elements[count++]); + + return count < stopCount; + }); + + BOOST_CHECK_EQUAL(count, stopCount); } BOOST_AUTO_TEST_CASE(uint256_key_wrapper) {