diff --git a/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.h b/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.h index 40b645f432ff9193971f62bd96b2f0f14cd6c3db..16be8f3572e18159334c02615d91b964b7baba91 100644 --- a/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.h +++ b/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.h @@ -479,6 +479,13 @@ public: size_t trim (const std::vector<key_query_type>& keys); + /** + * @brief Remove all entries in the container. + * Mostly for testing --- should not normally be used. + */ + void clear(); + + /** * @brief Return the current number of elements in the map. */ diff --git a/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.icc b/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.icc index c1f76ca0169a4018b7a4a3906ccd42277077950b..39d06f5148bbf3a9caac1b2eb7ee2733fcedbde9 100644 --- a/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.icc +++ b/Control/CxxUtils/CxxUtils/ConcurrentRangeMap.icc @@ -486,7 +486,7 @@ T_CONCURRENTRANGEMAP void CONCURRENTRANGEMAP::updateRanges (std::function<void (RANGE&)> rangeUpdater, const typename Updater_t::Context_t& ctx - /*= Updater_t::defaultContext()*/) + /*= Updater_t::defaultContext()*/) { lock_t lock (m_mutex); @@ -609,6 +609,38 @@ CONCURRENTRANGEMAP::trim (const std::vector<key_query_type>& keys) } +/** + * @brief Remove all entries in the container. + * Mostly for testing --- should not normally be used. + */ +T_CONCURRENTRANGEMAP +void CONCURRENTRANGEMAP::clear() +{ + lock_t lock (m_mutex); + + // Don't do anything if the container's already empty. + value_type* last = m_last; + if (last == nullptr) return; + + value_type* begin = m_begin; + + while (begin != last) { + mapped_type todel = begin->second; + ++begin; + m_begin = begin; + m_payloadDeleter->discard (todel); + } + + // Now have one element left. Be sure to clean m_begin first. + mapped_type todel = begin->second; + ++begin; + m_begin = nullptr; + m_last = nullptr; + m_begin = begin; + m_payloadDeleter->discard (todel); +} + + /** * @brief Return the current number of elements in the map. */ diff --git a/Control/CxxUtils/share/ConcurrentRangeMap_test.ref b/Control/CxxUtils/share/ConcurrentRangeMap_test.ref index 11ca5cbbb100bb0f0d72a26771ffcff60b29f8c9..b3de8bf1011e209cc76e893c3f16d53147e78c4d 100644 --- a/Control/CxxUtils/share/ConcurrentRangeMap_test.ref +++ b/Control/CxxUtils/share/ConcurrentRangeMap_test.ref @@ -1,4 +1,5 @@ test1a test1b test1c +test1d test2 diff --git a/Control/CxxUtils/test/ConcurrentRangeMap_test.cxx b/Control/CxxUtils/test/ConcurrentRangeMap_test.cxx index 27bb6abd39b07f16dbce61ed1fc1e44b9752c4cf..49ef80e9f9080124f439a601e0c7362116a62ea2 100644 --- a/Control/CxxUtils/test/ConcurrentRangeMap_test.cxx +++ b/Control/CxxUtils/test/ConcurrentRangeMap_test.cxx @@ -869,6 +869,34 @@ void test1c() } +// Test clear(); +void test1d() +{ + std::cout << "test1d\n"; + Payload::Hist phist; + TestMap map (TestMap::Updater_t(), std::make_shared<PayloadDeleter>(), 3); + assert (map.emplace (Range (10, 20), std::make_unique<Payload> (10, &phist)) == + TestMap::EmplaceResult::SUCCESS); + assert (map.emplace (Range (20, 30), std::make_unique<Payload> (20, &phist)) == + TestMap::EmplaceResult::SUCCESS); + assert (map.size() == 2); + assert (phist.size() == 2); + map.clear(); + assert (map.size() == 0); + assert (phist.size() == 2); + for (int i=0; i < nslots; i++) { + map.quiescent (i); + } + assert (map.size() == 0); + assert (phist.size() == 0); + + assert (map.emplace (Range (40, 50), std::make_unique<Payload> (40, &phist)) == + TestMap::EmplaceResult::SUCCESS); + assert (map.size() == 1); + assert (phist.size() == 1); +} + + //*************************************************************************** // Threaded test. // @@ -1088,6 +1116,7 @@ int main() test1a(); test1b(); test1c(); + test1d(); test2(); return 0; }