Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: third_party/bar/shared_ptr.h

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2006 and onwards Google Inc.
2 // Author: Michael Ellman (with suggestions from jrvb, m3b, toddw, jwray)
3 //
4 // A simple reference counted pointer implementation. It is a subset
5 // of the boost/tr1 shared_ptr class, which is expected to be part of
6 // the next C++ standard. See section 20.8.10 [util.smartptr] of the
7 // draft standard for a full description of the standard interface.
8 //
9 // Standard features that have been omitted from this implementation include:
10 // - no custom deallocators - uses delete
11 // - shared_ptr<T>'s constructor isn't templated: its argument is just T*.
12 // - no support for smart pointer casts
13 // - no support for unowned pointers
14 // - no support for variadic templates or rvalue references
15 // - no integration with auto_ptr or unique_ptr
16 // - not exception-safe
17 // - no overloaded comparison operators (e.g. operator<). They're
18 // convenient, but they can be explicitly defined outside the class.
19 //
20 // It's usually the case that when you want to share an object, there
21 // is a clear owner that outlives the other users. If that's the case,
22 // the owner can use scoped_ptr and the rest can use a raw pointer.
23 //
24 // A somewhat common design pattern that doesn't have a clear object
25 // owner is when there is a shared container in which older versions
26 // of an object are replaced with newer versions. The objects should be
27 // deleted only when (a) they are replaced with a new version and (b)
28 // there are no outside users of the old version. Replacing raw pointers
29 // in the implementation with shared_ptr's ensures that the accounting
30 // and object lifetimes are handled appropriately.
31 //
32 // The typical usage is as follows.
33 //
34 // 1. Functions using shared_ptr's should declare shared_ptr parameters to
35 // be of type const reference since the caller will still have its own
36 // shared_ptr for the entire call.
37 //
38 // void foo(const shared_ptr<T>& param)
39 //
40 // 2. Functions setting shared_ptr's should declare shared_ptr parameters
41 // to be of pointer type.
42 //
43 // typedef map<Key, shared_ptr<Value> > MyMap;
44 // void GetAndSharedObject(const Key& key, shared_ptr<Value>* value) {
45 // ReaderMutexLock l(&lock_);
46 // MyMap::iterator iter = shared_container.find(key);
47 // *value = iter->second;
48 // }
49 //
50 // Thread Safety:
51 // Once constructed, a shared_ptr has the same thread-safety as built-in
52 // types. In particular, it is safe to read a shared object simultaneously
53 // from multiple threads.
54 //
55 // Weak ptrs
56 // The weak_ptr auxiliary class (see clause 20.8.10.3 of the draft standard)
57 // is used to break ownership cycles. A weak_ptr points to an object that's
58 // owned by a shared_ptr, but the weak_ptr is an observer, not an owner. When
59 // the last shared_ptr that points to the object disappears, the weak_ptr
60 // expires, at which point the expired() member function will return true.
61 //
62 // You can't directly get a raw pointer from weak_ptr, i.e. it has no get()
63 // or operator*() member function. (These features were intentionally left out
64 // to avoid the risk of dangling pointers.) To access a weak_ptr's pointed-to
65 // object, use lock() to obtain a temporary shared_ptr.
66 //
67 // enable_shared_from_this
68 // A user-defined class T can inherit from enable_shared_from_this<T> (see
69 // clause 20.8.10.5 of the draft standard) to inherit T::shared_from_this(),
70 // which returns a shared_ptr pointing to *this. It is similar to weak_ptr in
71 // that there must already be at least one shared_ptr instance that owns
72 // *this.
73
74 #ifndef BAR_COMMON_SHARED_PTR_H_
75 #define BAR_COMMON_SHARED_PTR_H_
76
77 #include <windows.h>
78 #include <algorithm> // for swap
79
80 template <typename T> class shared_ptr;
81 template <typename T> class weak_ptr;
82
83 // This class is an internal implementation detail for shared_ptr. If two
84 // shared_ptrs point to the same object, they also share a control block.
85 // An "empty" shared_pointer refers to NULL and also has a NULL control block.
86 // It contains all of the state that's needed for reference counting or any
87 // other kind of resource management. In this implementation the control block
88 // happens to consist of two atomic words, the reference count (the number
89 // of shared_ptrs that share ownership of the object) and the weak count
90 // (the number of weak_ptrs that observe the object, plus 1 if the
91 // refcount is nonzero).
92 //
93 // The "plus 1" is to prevent a race condition in the shared_ptr and
94 // weak_ptr destructors. We need to make sure the control block is
95 // only deleted once, so we need to make sure that at most one
96 // object sees the weak count decremented from 1 to 0.
97 class SharedPtrControlBlock {
98 template <typename T> friend class shared_ptr;
99 template <typename T> friend class weak_ptr;
100 private:
101 SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
102 LONG refcount_;
103 LONG weak_count_;
104 };
105
106 // Forward declaration. The class is defined below.
107 template <typename T> class enable_shared_from_this;
108
109 template <typename T>
110 class shared_ptr {
111 template <typename U> friend class weak_ptr;
112 public:
113 typedef T element_type;
114
115 explicit shared_ptr(T* ptr = NULL)
116 : ptr_(ptr),
117 control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
118 // If p is non-null and T inherits from enable_shared_from_this, we
119 // set up the data that shared_from_this needs.
120 MaybeSetupWeakThis(ptr);
121 }
122
123 // Copy constructor: makes this object a copy of ptr, and increments
124 // the reference count.
125 template <typename U>
126 shared_ptr(const shared_ptr<U>& ptr)
127 : ptr_(NULL),
128 control_block_(NULL) {
129 Initialize(ptr);
130 }
131 // Need non-templated version to prevent the compiler-generated default
132 shared_ptr(const shared_ptr<T>& ptr)
133 : ptr_(NULL),
134 control_block_(NULL) {
135 Initialize(ptr);
136 }
137
138 // Assignment operator. Replaces the existing shared_ptr with ptr.
139 // Increment ptr's reference count and decrement the one being replaced.
140 template <typename U>
141 shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
142 if (ptr_ != ptr.ptr_) {
143 shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
144 swap(me);
145 }
146 return *this;
147 }
148
149 // Need non-templated version to prevent the compiler-generated default
150 shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
151 if (ptr_ != ptr.ptr_) {
152 shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
153 swap(me);
154 }
155 return *this;
156 }
157
158 // TODO(austern): Consider providing this constructor. The draft C++ standard
159 // (20.8.10.2.1) includes it. However, it says that this constructor throws
160 // a bad_weak_ptr exception when ptr is expired. Is it better to provide this
161 // constructor and make it do something else, like fail with a CHECK, or to
162 // leave this constructor out entirely?
163 //
164 // template <typename U>
165 // shared_ptr(const weak_ptr<U>& ptr);
166
167 ~shared_ptr() {
168 if (ptr_ != NULL) {
169 if (::InterlockedDecrement(&control_block_->refcount_) == 0) {
170 delete ptr_;
171
172 // weak_count_ is defined as the number of weak_ptrs that observe
173 // ptr_, plus 1 if refcount_ is nonzero.
174 if (::InterlockedDecrement(&control_block_->weak_count_) == 0) {
175 delete control_block_;
176 }
177 }
178 }
179 }
180
181 // Replaces underlying raw pointer with the one passed in. The reference
182 // count is set to one (or zero if the pointer is NULL) for the pointer
183 // being passed in and decremented for the one being replaced.
184 void reset(T* p = NULL) {
185 if (p != ptr_) {
186 shared_ptr<T> tmp(p);
187 tmp.swap(*this);
188 }
189 }
190
191 // Exchanges the contents of this with the contents of r. This function
192 // supports more efficient swapping since it eliminates the need for a
193 // temporary shared_ptr object.
194 void swap(shared_ptr<T>& r) {
195 std::swap(ptr_, r.ptr_);
196 std::swap(control_block_, r.control_block_);
197 }
198
199 // The following function is useful for gaining access to the underlying
200 // pointer when a shared_ptr remains in scope so the reference-count is
201 // known to be > 0 (e.g. for parameter passing).
202 T* get() const {
203 return ptr_;
204 }
205
206 T& operator*() const {
207 return *ptr_;
208 }
209
210 T* operator->() const {
211 return ptr_;
212 }
213
214 LONG use_count() const {
215 return control_block_ ? control_block_->refcount_ : 1;
216 }
217
218 bool unique() const {
219 return use_count() == 1;
220 }
221
222 private:
223 // If r is non-empty, initialize *this to share ownership with r,
224 // increasing the underlying reference count.
225 // If r is empty, *this remains empty.
226 // Requires: this is empty, namely this->ptr_ == NULL.
227 template <typename U>
228 void Initialize(const shared_ptr<U>& r) {
229 if (r.control_block_ != NULL) {
230 ::InterlockedIncrement(&r.control_block_->refcount_);
231
232 ptr_ = r.ptr_;
233 control_block_ = r.control_block_;
234 }
235 }
236
237 // Helper function for the constructor that takes a raw pointer. If T
238 // doesn't inherit from enable_shared_from_this<T> then we have nothing to
239 // do, so this function is trivial and inline. The other version is declared
240 // out of line, after the class definition of enable_shared_from_this.
241 void MaybeSetupWeakThis(enable_shared_from_this<T>* ptr);
242 void MaybeSetupWeakThis(...) { }
243
244 T* ptr_;
245 SharedPtrControlBlock* control_block_;
246
247 template <typename U>
248 friend class shared_ptr;
249 };
250
251 // Matches the interface of std::swap as an aid to generic programming.
252 template <typename T> void swap(shared_ptr<T>& r, shared_ptr<T>& s) {
253 r.swap(s);
254 }
255
256 // See comments at the top of the file for a description of why this
257 // class exists, and the draft C++ standard (as of July 2009 the
258 // latest draft is N2914) for the detailed specification.
259 template <typename T>
260 class weak_ptr {
261 template <typename U> friend class weak_ptr;
262 public:
263 typedef T element_type;
264
265 // Create an empty (i.e. already expired) weak_ptr.
266 weak_ptr() : ptr_(NULL), control_block_(NULL) { }
267
268 // Create a weak_ptr that observes the same object that ptr points
269 // to. Note that there is no race condition here: we know that the
270 // control block can't disappear while we're looking at it because
271 // it is owned by at least one shared_ptr, ptr.
272 template <typename U> weak_ptr(const shared_ptr<U>& ptr) {
273 CopyFrom(ptr.ptr_, ptr.control_block_);
274 }
275
276 // Copy a weak_ptr. The object it points to might disappear, but we
277 // don't care: we're only working with the control block, and it can't
278 // disappear while we're looking at because it's owned by at least one
279 // weak_ptr, ptr.
280 template <typename U> weak_ptr(const weak_ptr<U>& ptr) {
281 CopyFrom(ptr.ptr_, ptr.control_block_);
282 }
283
284 // Need non-templated version to prevent default copy constructor
285 weak_ptr(const weak_ptr& ptr) {
286 CopyFrom(ptr.ptr_, ptr.control_block_);
287 }
288
289 // Destroy the weak_ptr. If no shared_ptr owns the control block, and if
290 // we are the last weak_ptr to own it, then it can be deleted. Note that
291 // weak_count_ is defined as the number of weak_ptrs sharing this control
292 // block, plus 1 if there are any shared_ptrs. We therefore know that it's
293 // safe to delete the control block when weak_count_ reaches 0, without
294 // having to perform any additional tests.
295 ~weak_ptr() {
296 if (control_block_ != NULL &&
297 ::InterlockedDecrement(&control_block_->weak_count_) == 0) {
298 delete control_block_;
299 }
300 }
301
302 weak_ptr& operator=(const weak_ptr& ptr) {
303 if (&ptr != this) {
304 weak_ptr tmp(ptr);
305 tmp.swap(*this);
306 }
307 return *this;
308 }
309 template <typename U> weak_ptr& operator=(const weak_ptr<U>& ptr) {
310 weak_ptr tmp(ptr);
311 tmp.swap(*this);
312 return *this;
313 }
314 template <typename U> weak_ptr& operator=(const shared_ptr<U>& ptr) {
315 weak_ptr tmp(ptr);
316 tmp.swap(*this);
317 return *this;
318 }
319
320 void swap(weak_ptr& ptr) {
321 std::swap(ptr_, ptr.ptr_);
322 std::swap(control_block_, ptr.control_block_);
323 }
324
325 void reset() {
326 weak_ptr tmp;
327 tmp.swap(*this);
328 }
329
330 // Return the number of shared_ptrs that own the object we are observing.
331 // Note that this number can be 0 (if this pointer has expired).
332 LONG use_count() const {
333 return control_block_ != NULL ? control_block_->refcount_ : 0;
334 }
335
336 bool expired() const { return use_count() == 0; }
337
338 // Return a shared_ptr that owns the object we are observing. If we
339 // have expired, the shared_ptr will be empty. We have to be careful
340 // about concurrency, though, since some other thread might be
341 // destroying the last owning shared_ptr while we're in this
342 // function. We want to increment the refcount only if it's nonzero
343 // and get the new value, and we want that whole operation to be
344 // atomic.
345 shared_ptr<T> lock() const {
346 shared_ptr<T> result;
347 if (control_block_ != NULL) {
348 LONG old_refcount;
349 do {
350 old_refcount = control_block_->refcount_;
351 if (old_refcount == 0)
352 break;
353 } while (old_refcount !=
354 ::InterlockedCompareExchange(
355 &control_block_->refcount_, old_refcount + 1,
356 old_refcount));
357 if (old_refcount > 0) {
358 result.ptr_ = ptr_;
359 result.control_block_ = control_block_;
360 }
361 }
362
363 return result;
364 }
365
366 private:
367 void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
368 ptr_ = ptr;
369 control_block_ = control_block;
370 if (control_block_ != NULL)
371 ::InterlockedIncrement(&control_block_->weak_count_);
372 }
373
374 private:
375 element_type* ptr_;
376 SharedPtrControlBlock* control_block_;
377 };
378
379 template <typename T> void swap(weak_ptr<T>& r, weak_ptr<T>& s) {
380 r.swap(s);
381 }
382
383 // See comments at the top of the file for a description of why this class
384 // exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009
385 // the latest draft is N2914) for the detailed specification.
386 template <typename T>
387 class enable_shared_from_this {
388 friend class shared_ptr<T>;
389 public:
390 // Precondition: there must be a shared_ptr that owns *this and that was
391 // created, directly or indirectly, from a raw pointer of type T*. (The
392 // latter part of the condition is technical but not quite redundant; it
393 // rules out some complicated uses involving inheritance hierarchies.)
394 shared_ptr<T> shared_from_this() {
395 // Behavior is undefined if the precondition isn't satisfied; we choose
396 // to die with an access violation exception.
397 #if DEBUG
398 if (weak_this_.expired()) {
399 // No shared_ptr owns this object.
400 *static_cast<int*>(NULL) = 0;
401 }
402 #endif
403 return weak_this_.lock();
404 }
405 shared_ptr<const T> shared_from_this() const {
406 #if DEBUG
407 if (weak_this_.expired()) {
408 // No shared_ptr owns this object.
409 *static_cast<int*>(NULL) = 0;
410 }
411 #endif
412 return weak_this_.lock();
413 }
414
415 protected:
416 enable_shared_from_this() { }
417 enable_shared_from_this(const enable_shared_from_this& other) { }
418 enable_shared_from_this& operator=(const enable_shared_from_this& other) {
419 return *this;
420 }
421 ~enable_shared_from_this() { }
422
423 private:
424 weak_ptr<T> weak_this_;
425 };
426
427 // This is a helper function called by shared_ptr's constructor from a raw
428 // pointer. If T inherits from enable_shared_from_this<T>, it sets up
429 // weak_this_ so that shared_from_this works correctly. If T does not inherit
430 // from weak_this we get a different overload, defined inline, which does
431 // nothing.
432 template<typename T>
433 void shared_ptr<T>::MaybeSetupWeakThis(enable_shared_from_this<T>* ptr) {
434 if (ptr)
435 ptr->weak_this_ = *this;
436 }
437
438 #endif // BAR_COMMON_SHARED_PTR_H_
OLDNEW
« no previous file with comments | « testing/unittest_support/{CDABE316-39CD-43BA-8440-6D1E0547AEE6}.v3.gup ('k') | third_party/breakpad/build.scons » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698