summaryrefslogtreecommitdiffstats
path: root/o3d/compiler/puritan/puritan_shared_ptr.h
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/compiler/puritan/puritan_shared_ptr.h')
-rw-r--r--o3d/compiler/puritan/puritan_shared_ptr.h292
1 files changed, 292 insertions, 0 deletions
diff --git a/o3d/compiler/puritan/puritan_shared_ptr.h b/o3d/compiler/puritan/puritan_shared_ptr.h
new file mode 100644
index 0000000..ce1fa58
--- /dev/null
+++ b/o3d/compiler/puritan/puritan_shared_ptr.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// A simple reference counted pointer implementation. It is a subset
+// of the boost/tr1 shared_ptr class, which is expected to be part of
+// the next C++ standard. See section 20.6.6 [util.smartptr] of the
+// draft standard for a full description of the standard interface.
+//
+// The following standard features have been omitted from this implementation:
+// - no custom deallocators - uses delete
+// - no support for enable_shared_from_this
+// - no support for smart pointer casts
+// - no support for features that rely on variadic templates
+// - not exception-safe
+// - no overloaded comparison operators (e.g. operator<). They're
+// convenient, but they can be explicitly defined outside the class.
+//
+
+#ifndef UTIL_GTL_PURITAN_SHARED_PTR_H__
+#define UTIL_GTL_PURITAN_SHARED_PTR_H__
+
+#include <algorithm> // for swap
+
+template <typename T> class shared_ptr;
+template <typename T> class weak_ptr;
+
+// This class is an internal implementation detail for shared_ptr.
+//
+class SharedPtrControlBlock {
+ template <typename T> friend class shared_ptr;
+ template <typename T> friend class weak_ptr;
+ private:
+ SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
+ int refcount_;
+ int weak_count_;
+};
+
+template <typename T>
+class shared_ptr {
+ template <typename U> friend class weak_ptr;
+ public:
+ typedef T element_type;
+
+ explicit shared_ptr(T* ptr = NULL)
+ : ptr_(ptr),
+ control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
+ }
+
+ // Copy constructor: makes this object a copy of ptr
+ template <typename U>
+ shared_ptr(const shared_ptr<U>& ptr)
+ : ptr_(NULL),
+ control_block_(NULL) {
+ Initialize(ptr);
+ }
+ // Need non-templated version to prevent the compiler-generated default
+ shared_ptr(const shared_ptr<T>& ptr)
+ : ptr_(NULL),
+ control_block_(NULL) {
+ Initialize(ptr);
+ }
+
+ // Assignment operator. Replaces the existing shared_ptr with ptr.
+ template <typename U>
+ shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
+ if (ptr_ != ptr.ptr_) {
+ shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
+ swap(me);
+ }
+ return *this;
+ }
+
+ // Need non-templated version to prevent the compiler-generated default
+ shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
+ if (ptr_ != ptr.ptr_) {
+ shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
+ swap(me);
+ }
+ return *this;
+ }
+
+ ~shared_ptr() {
+ if (ptr_ != NULL) {
+ if (--control_block_->refcount_ == 0) {
+ delete ptr_;
+
+ // weak_count_ is defined as the number of weak_ptrs that observe
+ // ptr_, plus 1 if refcount_ is nonzero.
+ if (--control_block_->weak_count_ == 0) {
+ delete control_block_;
+ }
+ }
+ }
+ }
+
+ // Replaces underlying raw pointer with the one passed in. The reference
+ // count is set to one (or zero if the pointer is NULL) for the pointer
+ // being passed in and decremented for the one being replaced.
+ void reset(T* p = NULL) {
+ if (p != ptr_) {
+ shared_ptr<T> tmp(p);
+ tmp.swap(*this);
+ }
+ }
+
+ // Exchanges the contents of this with the contents of r. This function
+ // supports more efficient swapping since it eliminates the need for a
+ // temporary shared_ptr object.
+ void swap(shared_ptr<T>& r) {
+ std::swap(ptr_, r.ptr_);
+ std::swap(control_block_, r.control_block_);
+ }
+
+ // The following function is useful for gaining access to the underlying
+ // pointer when a shared_ptr remains in scope so the reference-count is
+ // known to be > 0 (e.g. for parameter passing).
+ T* get() const {
+ return ptr_;
+ }
+
+ T& operator*() const {
+ return *ptr_;
+ }
+
+ T* operator->() const {
+ return ptr_;
+ }
+
+ long use_count() const {
+ return control_block_ ? control_block_->refcount_ : 1;
+ }
+
+ bool unique() const {
+ return use_count() == 1;
+ }
+
+ private:
+ // If r is non-empty, initialize *this to share ownership with r,
+ // increasing the underlying reference count.
+ // If r is empty, *this remains empty.
+ // Requires: this is empty, namely this->ptr_ == NULL.
+ template <typename U>
+ void Initialize(const shared_ptr<U>& r) {
+ if (r.control_block_ != NULL) {
+ ++r.control_block_->refcount_;
+
+ ptr_ = r.ptr_;
+ control_block_ = r.control_block_;
+ }
+ }
+
+ T* ptr_;
+ SharedPtrControlBlock* control_block_;
+
+ template <typename U>
+ friend class shared_ptr;
+};
+
+// Matches the interface of std::swap as an aid to generic programming.
+template <typename T> void swap(shared_ptr<T>& r, shared_ptr<T>& s) {
+ r.swap(s);
+}
+
+// See comments at the top of the file for a description of why this
+// class exists, and the draft C++ standard (as of October 2007 the
+// latest draft is N2461) for the detailed specification.
+template <typename T>
+class weak_ptr {
+ template <typename U> friend class weak_ptr;
+ public:
+ typedef T element_type;
+
+ // Create an empty (i.e. already expired) weak_ptr.
+ weak_ptr() : ptr_(NULL), control_block_(NULL) { }
+
+ // Create a weak_ptr that observes the same object that ptr points
+ // to. Note that there is no race condition here: we know that the
+ // control block can't disappear while we're looking at it because
+ // it is owned by at least one shared_ptr, ptr.
+ template <typename U> weak_ptr(const shared_ptr<U>& ptr) {
+ CopyFrom(ptr.ptr_, ptr.control_block_);
+ }
+
+ // Copy a weak_ptr. The object it points to might disappear, but we
+ // don't care: we're only working with the control block, and it can't
+ // disappear while we're looking at because it's owned by at least one
+ // weak_ptr, ptr.
+ template <typename U> weak_ptr(const weak_ptr<U>& ptr) {
+ CopyFrom(ptr.ptr_, ptr.control_block_);
+ }
+
+ // Need non-templated version to prevent default copy constructor
+ weak_ptr(const weak_ptr& ptr) {
+ CopyFrom(ptr.ptr_, ptr.control_block_);
+ }
+
+ // Destroy the weak_ptr. If no shared_ptr owns the control block, and if
+ // we are the last weak_ptr to own it, then it can be deleted. Note that
+ // weak_count_ is defined as the number of weak_ptrs sharing this control
+ // block, plus 1 if there are any shared_ptrs. We therefore know that it's
+ // safe to delete the control block when weak_count_ reaches 0, without
+ // having to perform any additional tests.
+ ~weak_ptr() {
+ if (control_block_ != NULL &&
+ (--control_block_->weak_count_) == 0) {
+ delete control_block_;
+ }
+ }
+
+ weak_ptr& operator=(const weak_ptr& ptr) {
+ if (&ptr != this) {
+ weak_ptr tmp(ptr);
+ tmp.swap(*this);
+ }
+ return *this;
+ }
+ template <typename U> weak_ptr& operator=(const weak_ptr<U>& ptr) {
+ weak_ptr tmp(ptr);
+ tmp.swap(*this);
+ return *this;
+ }
+ template <typename U> weak_ptr& operator=(const shared_ptr<U>& ptr) {
+ weak_ptr tmp(ptr);
+ tmp.swap(*this);
+ return *this;
+ }
+
+ void swap(weak_ptr& ptr) {
+ ::swap(ptr_, ptr.ptr_);
+ ::swap(control_block_, ptr.control_block_);
+ }
+
+ void reset() {
+ weak_ptr tmp;
+ tmp.swap(*this);
+ }
+
+ // Return the number of shared_ptrs that own the object we are observing.
+ // Note that this number can be 0 (if this pointer has expired).
+ long use_count() const {
+ return control_block_ != NULL ? control_block_->refcount_ : 0;
+ }
+
+ bool expired() const { return use_count() == 0; }
+
+ private:
+ void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
+ ptr_ = ptr;
+ control_block_ = control_block;
+ if (control_block_ != NULL)
+ ++control_block_->weak_count_;
+ }
+
+ private:
+ element_type* ptr_;
+ SharedPtrControlBlock* control_block_;
+};
+
+template <typename T> void swap(weak_ptr<T>& r, weak_ptr<T>& s) {
+ r.swap(s);
+}
+
+#endif // UTIL_GTL_PURITAN_SHARED_PTR_H__