mirror of
https://github.com/ceph/ceph
synced 2024-12-25 04:43:17 +00:00
4c4e1d0d47
Switches the implemetnation of smart pointers and unordered map/set to use the ceph:: versions. Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
192 lines
4.1 KiB
C++
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
|