]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/sharedptr_registry.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / common / sharedptr_registry.hpp
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
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.
12 *
13 */
14
15#ifndef CEPH_SHAREDPTR_REGISTRY_H
16#define CEPH_SHAREDPTR_REGISTRY_H
17
18#include <map>
19#include <memory>
11fdf7f2 20#include "common/ceph_mutex.h"
7c673cae
FG
21
22/**
23 * Provides a registry of shared_ptr<V> indexed by K while
24 * the references are alive.
25 */
26template <class K, class V, class C = std::less<K> >
27class SharedPtrRegistry {
28public:
11fdf7f2
TL
29 typedef std::shared_ptr<V> VPtr;
30 typedef std::weak_ptr<V> WeakVPtr;
7c673cae
FG
31 int waiting;
32private:
11fdf7f2
TL
33 ceph::mutex lock = ceph::make_mutex("SharedPtrRegistry::lock");
34 ceph::condition_variable cond;
35 std::map<K, std::pair<WeakVPtr, V*>, C> contents;
7c673cae
FG
36
37 class OnRemoval {
38 SharedPtrRegistry<K,V,C> *parent;
39 K key;
40 public:
41 OnRemoval(SharedPtrRegistry<K,V,C> *parent, K key) :
42 parent(parent), key(key) {}
43 void operator()(V *to_remove) {
44 {
11fdf7f2
TL
45 std::lock_guard l(parent->lock);
46 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
47 parent->contents.find(key);
48 if (i != parent->contents.end() &&
49 i->second.second == to_remove) {
50 parent->contents.erase(i);
11fdf7f2 51 parent->cond.notify_all();
7c673cae
FG
52 }
53 }
54 delete to_remove;
55 }
56 };
57 friend class OnRemoval;
58
59public:
60 SharedPtrRegistry() :
11fdf7f2 61 waiting(0)
7c673cae
FG
62 {}
63
64 bool empty() {
11fdf7f2 65 std::lock_guard l(lock);
7c673cae
FG
66 return contents.empty();
67 }
68
11fdf7f2
TL
69 bool get_next(const K &key, std::pair<K, VPtr> *next) {
70 std::pair<K, VPtr> r;
7c673cae 71 {
11fdf7f2 72 std::lock_guard l(lock);
7c673cae 73 VPtr next_val;
11fdf7f2 74 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
75 contents.upper_bound(key);
76 while (i != contents.end() &&
77 !(next_val = i->second.first.lock()))
78 ++i;
79 if (i == contents.end())
80 return false;
81 if (next)
11fdf7f2 82 r = std::make_pair(i->first, next_val);
7c673cae
FG
83 }
84 if (next)
85 *next = r;
86 return true;
87 }
88
89
11fdf7f2 90 bool get_next(const K &key, std::pair<K, V> *next) {
7c673cae 91 VPtr next_val;
11fdf7f2
TL
92 std::lock_guard l(lock);
93 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
94 contents.upper_bound(key);
95 while (i != contents.end() &&
96 !(next_val = i->second.first.lock()))
97 ++i;
98 if (i == contents.end())
99 return false;
100 if (next)
11fdf7f2 101 *next = std::make_pair(i->first, *next_val);
7c673cae
FG
102 return true;
103 }
104
105 VPtr lookup(const K &key) {
11fdf7f2 106 std::unique_lock l(lock);
7c673cae
FG
107 waiting++;
108 while (1) {
11fdf7f2 109 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
110 contents.find(key);
111 if (i != contents.end()) {
112 VPtr retval = i->second.first.lock();
113 if (retval) {
114 waiting--;
115 return retval;
116 }
117 } else {
118 break;
119 }
11fdf7f2 120 cond.wait(l);
7c673cae
FG
121 }
122 waiting--;
123 return VPtr();
124 }
125
126 VPtr lookup_or_create(const K &key) {
11fdf7f2 127 std::unique_lock l(lock);
7c673cae
FG
128 waiting++;
129 while (1) {
11fdf7f2 130 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
131 contents.find(key);
132 if (i != contents.end()) {
133 VPtr retval = i->second.first.lock();
134 if (retval) {
135 waiting--;
136 return retval;
137 }
138 } else {
139 break;
140 }
11fdf7f2 141 cond.wait(l);
7c673cae
FG
142 }
143 V *ptr = new V();
144 VPtr retval(ptr, OnRemoval(this, key));
11fdf7f2 145 contents.insert(std::make_pair(key, make_pair(retval, ptr)));
7c673cae
FG
146 waiting--;
147 return retval;
148 }
149
150 unsigned size() {
11fdf7f2 151 std::lock_guard l(lock);
7c673cae
FG
152 return contents.size();
153 }
154
155 void remove(const K &key) {
11fdf7f2 156 std::lock_guard l(lock);
7c673cae 157 contents.erase(key);
11fdf7f2 158 cond.notify_all();
7c673cae
FG
159 }
160
161 template<class A>
162 VPtr lookup_or_create(const K &key, const A &arg) {
11fdf7f2 163 std::unique_lock l(lock);
7c673cae
FG
164 waiting++;
165 while (1) {
11fdf7f2 166 typename std::map<K, std::pair<WeakVPtr, V*>, C>::iterator i =
7c673cae
FG
167 contents.find(key);
168 if (i != contents.end()) {
169 VPtr retval = i->second.first.lock();
170 if (retval) {
171 waiting--;
172 return retval;
173 }
174 } else {
175 break;
176 }
11fdf7f2 177 cond.wait(l);
7c673cae
FG
178 }
179 V *ptr = new V(arg);
180 VPtr retval(ptr, OnRemoval(this, key));
11fdf7f2 181 contents.insert(std::make_pair(key, make_pair(retval, ptr)));
7c673cae
FG
182 waiting--;
183 return retval;
184 }
185
186 friend class SharedPtrRegistryTest;
187};
188
189#endif