From 3ed487fdce0e8f9894f0b339816c6c3d39aa478d Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 8 Dec 2015 13:18:47 -0500 Subject: [PATCH] weakset/map update note that size() can give larger than actual. Skip dead entries in lock_*() instead of throwing. --- p2pApp/weakmap.h | 20 ++++++++++++++------ p2pApp/weakset.h | 11 ++++++++--- testApp/testweak.cpp | 30 +++++++++++++++++------------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/p2pApp/weakmap.h b/p2pApp/weakmap.h index 81ad0d8..f898a1b 100644 --- a/p2pApp/weakmap.h +++ b/p2pApp/weakmap.h @@ -130,6 +130,7 @@ public: //! Test if set is empty at this moment //! @note Thread safe + //! @warning see size() bool empty() const { guard_type G(m_data->mutex); return m_data->store.empty(); @@ -137,6 +138,8 @@ public: //! number of entries in the set at this moment //! @note Thread safe + //! @warning May be momentarily inaccurate (larger) due to dead refs. + //! which have not yet been removed. size_t size() const { guard_type G(m_data->mutex); return m_data->store.size(); @@ -202,8 +205,11 @@ public: value_pointer ret; guard_type G(m_data->mutex); typename store_t::const_iterator it(m_data->store.find(k)); - if(it!=m_data->store.end()) - ret = it->second.lock(); // may be nullptr if we race destruction + if(it!=m_data->store.end()) { + // may be nullptr if we race destruction + // as ref. count falls to zero before we can remove it + ret = it->second.lock(); + } return ret; } @@ -224,12 +230,13 @@ public: //! Return an equivalent map with strong value references lock_map_type lock_map() const { - std::map ret; + lock_map_type ret; guard_type G(m_data->mutex); for(typename store_t::const_iterator it = m_data->store.begin(), end = m_data->store.end(); it!=end; ++it) { - ret[it->first] = it->second.lock(); + value_pointer P(it->second.lock); + if(P) ret[it->first] = P; } return ret; } @@ -239,13 +246,14 @@ public: //! useful for iteration lock_vector_type lock_vector() const { - std::vector > ret; + lock_vector_type ret; guard_type G(m_data->mutex); ret.reserve(m_data->store.size()); for(typename store_t::const_iterator it = m_data->store.begin(), end = m_data->store.end(); it!=end; ++it) { - ret.push_back(std::make_pair(it->first, it->second.lock())); + value_pointer P(it->second.lock()); + if(P) ret.push_back(std::make_pair(it->first, P)); } return ret; } diff --git a/p2pApp/weakset.h b/p2pApp/weakset.h index a0e5ae2..7d73678 100644 --- a/p2pApp/weakset.h +++ b/p2pApp/weakset.h @@ -150,8 +150,9 @@ public: return m_data->store.clear(); } - //! Test if set is empty at this moment + //! Test if set is empty //! @note Thread safe + //! @warning see size() bool empty() const { guard_type G(m_data->mutex); return m_data->store.empty(); @@ -159,6 +160,8 @@ public: //! number of entries in the set at this moment //! @note Thread safe + //! @warning May be momentarily inaccurate (larger) due to dead refs. + //! which have not yet been removed. size_t size() const { guard_type G(m_data->mutex); return m_data->store.size(); @@ -228,7 +231,8 @@ weak_set::lock_set() const for(typename store_t::const_iterator it=m_data->store.begin(), end=m_data->store.end(); it!=end; ++it) { - ret.insert(value_pointer(*it)); + value_pointer P(it->lock()); + if(P) ret.insert(P); } return ret; } @@ -243,7 +247,8 @@ weak_set::lock_vector() const for(typename store_t::const_iterator it=m_data->store.begin(), end=m_data->store.end(); it!=end; ++it) { - ret.push_back(value_pointer(*it)); + value_pointer P(it->lock()); + if(P) ret.push_back(P); } return ret; } diff --git a/testApp/testweak.cpp b/testApp/testweak.cpp index e978eb1..c85ee68 100644 --- a/testApp/testweak.cpp +++ b/testApp/testweak.cpp @@ -12,8 +12,9 @@ void testWeakSet1() { testDiag("Test1 weak_set"); - weak_set::value_pointer ptr; - weak_set set; + typedef weak_set set_type; + set_type set; + set_type::value_pointer ptr; testOk1(set.empty()); @@ -25,13 +26,13 @@ void testWeakSet1() testOk1(ptr.unique()); // we hold the only "fake" strong ref. { - weak_set::set_type S(set.lock_set()); + set_type::set_type S(set.lock_set()); testOk1(!S.empty()); testOk1(S.size()==1); testOk1(S.find(ptr)!=S.end()); } { - weak_set::vector_type S(set.lock_vector()); + set_type::vector_type S(set.lock_vector()); testOk1(!S.empty()); testOk1(S.size()==1); testOk1(*S[0]==5); @@ -43,8 +44,9 @@ void testWeakSet2() { testDiag("Test2 weak_set"); - weak_set set; - weak_set::value_pointer ptr; + typedef weak_set set_type; + set_type set; + set_type::value_pointer ptr; testOk1(set.empty()); @@ -89,8 +91,9 @@ void testWeakMap1() { testDiag("Test weak_value_map1"); - weak_set::value_pointer ptr; - weak_value_map map; + typedef weak_value_map map_type; + map_type::value_pointer ptr; + map_type map; testOk1(map.empty()); @@ -99,7 +102,7 @@ void testWeakMap1() testOk1(!map.empty()); { - weak_value_map::lock_vector_type V(map.lock_vector()); + map_type::lock_vector_type V(map.lock_vector()); testOk1(V.size()==1); testOk1(V[0].first==4); testOk1(*V[0].second==5); @@ -114,8 +117,9 @@ void testWeakMap2() { testDiag("Test weak_value_map2"); - weak_set::value_pointer ptr; - weak_value_map map; + typedef weak_value_map map_type; + map_type::value_pointer ptr; + map_type map; testOk1(map.empty()); @@ -124,7 +128,7 @@ void testWeakMap2() testOk1(!map.empty()); { - weak_value_map::lock_vector_type V(map.lock_vector()); + map_type::lock_vector_type V(map.lock_vector()); testOk1(V.size()==1); testOk1(V[0].first==4); testOk1(*V[0].second==5); @@ -136,7 +140,7 @@ void testWeakMap2() ptr.reset(new int(5)); map[4] = ptr; { - weak_set::value_pointer O(map[4]); + map_type::value_pointer O(map[4]); testOk1(O==ptr); }