diff --git a/p2pApp/weakset.h b/p2pApp/weakset.h index 9029864..1b5a156 100644 --- a/p2pApp/weakset.h +++ b/p2pApp/weakset.h @@ -195,6 +195,27 @@ public: return m_data->mutex; } + //! an iterator-ish object which also locks the set during iteration + struct XIterator { + weak_set& set; + epicsGuard guard; + typename store_t::iterator it, end; + XIterator(weak_set& S) :set(S), guard(S.mutex()), it(S.m_data->store.begin()), end(S.m_data->store.end()) {} + //! yield the next live entry + value_pointer next() { + value_pointer ret; + while(it!=end) { + ret = (it++)->lock(); + if(ret) break; + } + return ret; + } + private: + XIterator(const XIterator&); + XIterator& operator=(const XIterator&); + }; + + typedef XIterator iterator; }; template diff --git a/testApp/testweak.cpp b/testApp/testweak.cpp index 43cea54..0f60f90 100644 --- a/testApp/testweak.cpp +++ b/testApp/testweak.cpp @@ -165,16 +165,49 @@ void testWeakLock() } } +static +void testWeakIterate() +{ + typedef weak_set set_type; + set_type::value_pointer A, B; + set_type set; + + testDiag("Test weak_set locked iteration"); + + A.reset(new int(42)); + set.insert(A); + A.reset(new int(43)); + // ref. to 42 is dropped + set.insert(A); + B.reset(new int(44)); + set.insert(B); + + testOk1(set.size()==2); + + { + set_type::iterator it(set); + set_type::value_pointer V; + + V = it.next(); + testOk1(V && (*V==43 || *V==44)); + V = it.next(); + testOk1(V && (*V==43 || *V==44)); + V = it.next(); + testOk1(!V); + } +} + } // namespace MAIN(testweak) { - testPlan(33); + testPlan(37); testWeakSet1(); testWeakSet2(); testWeakSetInvalid(); testWeakMap1(); testWeakMap2(); testWeakLock(); + testWeakIterate(); return testDone(); }