1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #ifndef CEPH_SHAREDPTR_REGISTRY_H
16 #define CEPH_SHAREDPTR_REGISTRY_H
20 #include "common/ceph_mutex.h"
23 * Provides a registry of shared_ptr<V> indexed by K while
24 * the references are alive.
26 template <class K, class V, class C = std::less<K> >
27 class SharedPtrRegistry {
29 typedef std::shared_ptr<V> VPtr;
30 typedef std::weak_ptr<V> WeakVPtr;
33 ceph::mutex lock = ceph::make_mutex("SharedPtrRegistry::lock");
34 ceph::condition_variable cond;
35 std::map<K, std::pair<WeakVPtr, V*>, C> contents;
38 SharedPtrRegistry<K,V,C> *parent;
41 OnRemoval(SharedPtrRegistry<K,V,C> *parent, K key) :
42 parent(parent), key(key) {}
43 void operator()(V *to_remove) {
45 std::lock_guard l(parent->lock);
46 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
47 parent->contents.find(key);
48 if (i != parent->contents.end() &&
49 i->second.second == to_remove) {
50 parent->contents.erase(i);
51 parent->cond.notify_all();
57 friend class OnRemoval;
65 std::lock_guard l(lock);
66 return contents.empty();
69 bool get_next(const K &key, std::pair<K, VPtr> *next) {
72 std::lock_guard l(lock);
74 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
75 contents.upper_bound(key);
76 while (i != contents.end() &&
77 !(next_val = i->second.first.lock()))
79 if (i == contents.end())
82 r = std::make_pair(i->first, next_val);
90 bool get_next(const K &key, std::pair<K, V> *next) {
92 std::lock_guard l(lock);
93 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
94 contents.upper_bound(key);
95 while (i != contents.end() &&
96 !(next_val = i->second.first.lock()))
98 if (i == contents.end())
101 *next = std::make_pair(i->first, *next_val);
105 VPtr lookup(const K &key) {
106 std::unique_lock l(lock);
109 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
111 if (i != contents.end()) {
112 VPtr retval = i->second.first.lock();
126 VPtr lookup_or_create(const K &key) {
127 std::unique_lock l(lock);
130 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
132 if (i != contents.end()) {
133 VPtr retval = i->second.first.lock();
144 VPtr retval(ptr, OnRemoval(this, key));
145 contents.insert(std::make_pair(key, make_pair(retval, ptr)));
151 std::lock_guard l(lock);
152 return contents.size();
155 void remove(const K &key) {
156 std::lock_guard l(lock);
162 VPtr lookup_or_create(const K &key, const A &arg) {
163 std::unique_lock l(lock);
166 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
168 if (i != contents.end()) {
169 VPtr retval = i->second.first.lock();
180 VPtr retval(ptr, OnRemoval(this, key));
181 contents.insert(std::make_pair(key, make_pair(retval, ptr)));
186 friend class SharedPtrRegistryTest;