ceph/src/common/sharedptr_registry.hpp
Noah Watkins 4c4e1d0d47 libc++: use ceph:: namespaced data types
Switches the implemetnation of smart pointers and unordered map/set to
use the ceph:: versions.

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
2014-01-18 14:03:20 -08:00

192 lines
4.1 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#ifndef CEPH_SHAREDPTR_REGISTRY_H
#define CEPH_SHAREDPTR_REGISTRY_H
#include <map>
#include <memory>
#include "common/Mutex.h"
#include "common/Cond.h"
/**
* Provides a registry of shared_ptr<V> indexed by K while
* the references are alive.
*/
template <class K, class V>
class SharedPtrRegistry {
public:
typedef ceph::shared_ptr<V> VPtr;
typedef ceph::weak_ptr<V> WeakVPtr;
int waiting;
private:
Mutex lock;
Cond cond;
map<K, pair<WeakVPtr, V*> > contents;
class OnRemoval {
SharedPtrRegistry<K,V> *parent;
K key;
public:
OnRemoval(SharedPtrRegistry<K,V> *parent, K key) :
parent(parent), key(key) {}
void operator()(V *to_remove) {
{
Mutex::Locker l(parent->lock);
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;
}
};
friend class OnRemoval;
public:
SharedPtrRegistry() :
waiting(0),
lock("SharedPtrRegistry::lock")
{}
bool empty() {
Mutex::Locker l(lock);
return contents.empty();
}
bool get_next(const K &key, pair<K, VPtr> *next) {
pair<K, VPtr> r;
{
Mutex::Locker l(lock);
VPtr next_val;
typename map<K, pair<WeakVPtr, V*> >::iterator i =
contents.upper_bound(key);
while (i != contents.end() &&
!(next_val = i->second.first.lock()))
++i;
if (i == contents.end())
return false;
if (next)
r = make_pair(i->first, next_val);
}
if (next)
*next = r;
return true;
}
bool get_next(const K &key, pair<K, V> *next) {
VPtr next_val;
Mutex::Locker l(lock);
typename map<K, pair<WeakVPtr, V*> >::iterator i =
contents.upper_bound(key);
while (i != contents.end() &&
!(next_val = i->second.first.lock()))
++i;
if (i == contents.end())
return false;
if (next)
*next = make_pair(i->first, *next_val);
return true;
}
VPtr lookup(const K &key) {
Mutex::Locker l(lock);
waiting++;
while (1) {
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;
}
} else {
break;
}
cond.Wait(lock);
}
waiting--;
return VPtr();
}
VPtr lookup_or_create(const K &key) {
Mutex::Locker l(lock);
waiting++;
while (1) {
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;
}
} else {
break;
}
cond.Wait(lock);
}
V *ptr = new V();
VPtr retval(ptr, OnRemoval(this, key));
contents.insert(make_pair(key, make_pair(retval, ptr)));
waiting--;
return retval;
}
unsigned size() {
Mutex::Locker l(lock);
return contents.size();
}
void remove(const K &key) {
Mutex::Locker l(lock);
contents.erase(key);
cond.Signal();
}
template<class A>
VPtr lookup_or_create(const K &key, const A &arg) {
Mutex::Locker l(lock);
waiting++;
while (1) {
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;
}
} else {
break;
}
cond.Wait(lock);
}
V *ptr = new V(arg);
VPtr retval(ptr, OnRemoval(this, key));
contents.insert(make_pair(key, make_pair(retval, ptr)));
waiting--;
return retval;
}
friend class SharedPtrRegistryTest;
};
#endif