]>
Commit | Line | Data |
---|---|---|
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 | */ | |
26 | template <class K, class V, class C = std::less<K> > | |
27 | class SharedPtrRegistry { | |
28 | public: | |
11fdf7f2 TL |
29 | typedef std::shared_ptr<V> VPtr; |
30 | typedef std::weak_ptr<V> WeakVPtr; | |
7c673cae FG |
31 | int waiting; |
32 | private: | |
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 | ||
59 | public: | |
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 |