private:
Mutex lock;
Cond cond;
- map<K, WeakVPtr> contents;
+ map<K, pair<WeakVPtr, V*> > contents;
class OnRemoval {
SharedPtrRegistry<K,V> *parent;
void operator()(V *to_remove) {
{
Mutex::Locker l(parent->lock);
- parent->contents.erase(key);
- parent->cond.Signal();
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ parent->contents.find(key);
+ if (i != parent->contents.end() &&
+ i->second.second == to_remove) {
+ parent->contents.erase(i);
+ parent->cond.Signal();
+ }
}
delete to_remove;
}
{
Mutex::Locker l(lock);
VPtr next_val;
- typename map<K, WeakVPtr>::iterator i = contents.upper_bound(key);
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ contents.upper_bound(key);
while (i != contents.end() &&
- !(next_val = i->second.lock()))
+ !(next_val = i->second.first.lock()))
++i;
if (i == contents.end())
return false;
bool get_next(const K &key, pair<K, V> *next) {
VPtr next_val;
Mutex::Locker l(lock);
- typename map<K, WeakVPtr>::iterator i = contents.upper_bound(key);
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ contents.upper_bound(key);
while (i != contents.end() &&
- !(next_val = i->second.lock()))
+ !(next_val = i->second.first.lock()))
++i;
if (i == contents.end())
return false;
Mutex::Locker l(lock);
waiting++;
while (1) {
- if (contents.count(key)) {
- VPtr retval = contents[key].lock();
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ contents.find(key);
+ if (i != contents.end()) {
+ VPtr retval = i->second.first.lock();
if (retval) {
waiting--;
return retval;
Mutex::Locker l(lock);
waiting++;
while (1) {
- if (contents.count(key)) {
- VPtr retval = contents[key].lock();
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ contents.find(key);
+ if (i != contents.end()) {
+ VPtr retval = i->second.first.lock();
if (retval) {
waiting--;
return retval;
}
cond.Wait(lock);
}
- VPtr retval(new V(), OnRemoval(this, key));
- contents[key] = retval;
+ V *ptr = new V();
+ VPtr retval(ptr, OnRemoval(this, key));
+ contents.insert(make_pair(key, make_pair(retval, ptr)));
waiting--;
return retval;
}
Mutex::Locker l(lock);
waiting++;
while (1) {
- if (contents.count(key)) {
- VPtr retval = contents[key].lock();
+ typename map<K, pair<WeakVPtr, V*> >::iterator i =
+ contents.find(key);
+ if (i != contents.end()) {
+ VPtr retval = i->second.first.lock();
if (retval) {
waiting--;
return retval;
}
cond.Wait(lock);
}
- VPtr retval(new V(arg), OnRemoval(this, key));
- contents[key] = retval;
+ V *ptr = new V(arg);
+ VPtr retval(ptr, OnRemoval(this, key));
+ contents.insert(make_pair(key, make_pair(retval, ptr)));
waiting--;
return retval;
}
class SharedPtrRegistryTest : public SharedPtrRegistry<unsigned int, int> {
public:
Mutex &get_lock() { return lock; }
- map<unsigned int, weak_ptr<int> > &get_contents() { return contents; }
+ map<unsigned int, pair<weak_ptr<int>, int*> > &get_contents() {
+ return contents;
+ }
};
class SharedPtrRegistry_all : public ::testing::Test {
unsigned int key = 1;
{
shared_ptr<int> ptr(new int);
- registry.get_contents()[key] = ptr;
+ registry.get_contents()[key] = make_pair(ptr, ptr.get());
}
- EXPECT_FALSE(registry.get_contents()[key].lock());
+ EXPECT_FALSE(registry.get_contents()[key].first.lock());
Thread_wait t(registry, key, 0, Thread_wait::LOOKUP_OR_CREATE);
t.create();
int value = 3;
{
shared_ptr<int> ptr(new int);
- registry.get_contents()[key] = ptr;
+ registry.get_contents()[key] = make_pair(ptr, ptr.get());
}
- EXPECT_FALSE(registry.get_contents()[key].lock());
+ EXPECT_FALSE(registry.get_contents()[key].first.lock());
Thread_wait t(registry, key, value, Thread_wait::LOOKUP_OR_CREATE);
t.create();
int value = 2;
{
shared_ptr<int> ptr(new int);
- registry.get_contents()[key] = ptr;
+ registry.get_contents()[key] = make_pair(ptr, ptr.get());
}
- EXPECT_FALSE(registry.get_contents()[key].lock());
+ EXPECT_FALSE(registry.get_contents()[key].first.lock());
Thread_wait t(registry, key, value, Thread_wait::LOOKUP);
t.create();
// entries with expired pointers are silentely ignored
const unsigned int key_gone = 222;
- registry.get_contents()[key_gone] = shared_ptr<int>();
+ registry.get_contents()[key_gone] = make_pair(shared_ptr<int>(), (int*)0);
const unsigned int key1 = 111;
shared_ptr<int> ptr1 = registry.lookup_or_create(key1);
}
}
+TEST_F(SharedPtrRegistry_all, remove) {
+ {
+ SharedPtrRegistryTest registry;
+ const unsigned int key1 = 1;
+ shared_ptr<int> ptr1 = registry.lookup_or_create(key1);
+ *ptr1 = 400;
+ registry.remove(key1);
+
+ shared_ptr<int> ptr2 = registry.lookup_or_create(key1);
+ *ptr2 = 500;
+
+ ptr1 = shared_ptr<int>();
+ shared_ptr<int> res = registry.lookup(key1);
+ assert(res);
+ assert(res == ptr2);
+ assert(*res == 500);
+ }
+ {
+ SharedPtrRegistryTest registry;
+ const unsigned int key1 = 1;
+ shared_ptr<int> ptr1 = registry.lookup_or_create(key1, 400);
+ registry.remove(key1);
+
+ shared_ptr<int> ptr2 = registry.lookup_or_create(key1, 500);
+
+ ptr1 = shared_ptr<int>();
+ shared_ptr<int> res = registry.lookup(key1);
+ assert(res);
+ assert(res == ptr2);
+ assert(*res == 500);
+ }
+}
+
class SharedPtrRegistry_destructor : public ::testing::Test {
public: