weakset/map update

note that size() can give larger than actual.
Skip dead entries in lock_*() instead of throwing.
This commit is contained in:
Michael Davidsaver
2015-12-08 13:18:47 -05:00
parent 81881d90ae
commit 3ed487fdce
3 changed files with 39 additions and 22 deletions

View File

@ -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<K, value_pointer, C> 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<std::pair<K, value_pointer> > 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;
}

View File

@ -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<T>::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<T>::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;
}

View File

@ -12,8 +12,9 @@ void testWeakSet1()
{
testDiag("Test1 weak_set");
weak_set<int>::value_pointer ptr;
weak_set<int> set;
typedef weak_set<int> 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<int>::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<int>::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<int> set;
weak_set<int>::value_pointer ptr;
typedef weak_set<int> 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<int>::value_pointer ptr;
weak_value_map<int,int> map;
typedef weak_value_map<int,int> 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<int,int>::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<int>::value_pointer ptr;
weak_value_map<int,int> map;
typedef weak_value_map<int,int> 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<int,int>::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<int>::value_pointer O(map[4]);
map_type::value_pointer O(map[4]);
testOk1(O==ptr);
}