add shared_pr.h
This commit is contained in:
parent
bde4a3254a
commit
7580a8929f
3 changed files with 480 additions and 9 deletions
|
@ -103,7 +103,6 @@ def use_setuptools(
|
|||
sys.path.insert(0, egg)
|
||||
import setuptools; setuptools.bootstrap_install_from = egg
|
||||
try:
|
||||
return do_download()
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
return do_download()
|
||||
|
|
|
@ -8,14 +8,17 @@ import subprocess
|
|||
# We must use setuptools, not distutils, because we need to use the
|
||||
# namespace_packages option for the "google" package.
|
||||
try:
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
from setuptools import setup, Extension, __version__
|
||||
from setuptools import setup, Extension
|
||||
except ImportError:
|
||||
sys.stderr.write(
|
||||
"Could not import setuptools; make sure you have setuptools or "
|
||||
"ez_setup installed.\n")
|
||||
raise
|
||||
try:
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
from setuptools import setup, Extension
|
||||
except ImportError:
|
||||
sys.stderr.write(
|
||||
"Could not import setuptools; make sure you have setuptools or "
|
||||
"ez_setup installed.\n")
|
||||
raise
|
||||
from distutils.command.clean import clean as _clean
|
||||
from distutils.command.build_py import build_py as _build_py
|
||||
from distutils.spawn import find_executable
|
||||
|
@ -118,7 +121,6 @@ class build_py(_build_py):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__version__)
|
||||
# C++ implementation extension
|
||||
nocpp = '--nocpp_implementation'
|
||||
if nocpp in sys.argv:
|
||||
|
|
470
src/google/protobuf/stubs/shared_ptr.h
Normal file
470
src/google/protobuf/stubs/shared_ptr.h
Normal file
|
@ -0,0 +1,470 @@
|
|||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// 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.
|
||||
|
||||
// from google3/util/gtl/shared_ptr.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
|
||||
#include <algorithm> // for swap
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Alias to std::shared_ptr for any C++11 platform,
|
||||
// and for any supported MSVC compiler.
|
||||
#if !defined(UTIL_GTL_USE_STD_SHARED_PTR) && \
|
||||
(defined(COMPILER_MSVC) || defined(LANG_CXX11))
|
||||
#define UTIL_GTL_USE_STD_SHARED_PTR 1
|
||||
#endif
|
||||
|
||||
#if defined(UTIL_GTL_USE_STD_SHARED_PTR) && UTIL_GTL_USE_STD_SHARED_PTR
|
||||
|
||||
// These are transitional. They will be going away soon.
|
||||
// Please just #include <memory> and just type std::shared_ptr yourself, instead
|
||||
// of relying on this file.
|
||||
//
|
||||
// Migration doc: http://go/std-shared-ptr-lsc
|
||||
using std::enable_shared_from_this;
|
||||
using std::shared_ptr;
|
||||
using std::static_pointer_cast;
|
||||
using std::weak_ptr;
|
||||
|
||||
#else // below, UTIL_GTL_USE_STD_SHARED_PTR not set or set to 0.
|
||||
|
||||
// For everything else there is the google3 implementation.
|
||||
inline bool RefCountDec(volatile Atomic32 *ptr) {
|
||||
return Barrier_AtomicIncrement(ptr, -1) != 0;
|
||||
}
|
||||
|
||||
inline void RefCountInc(volatile Atomic32 *ptr) {
|
||||
NoBarrier_AtomicIncrement(ptr, 1);
|
||||
}
|
||||
|
||||
template <typename T> class shared_ptr;
|
||||
template <typename T> class weak_ptr;
|
||||
|
||||
// This class is an internal implementation detail for shared_ptr. If two
|
||||
// shared_ptrs point to the same object, they also share a control block.
|
||||
// An "empty" shared_pointer refers to NULL and also has a NULL control block.
|
||||
// It contains all of the state that's needed for reference counting or any
|
||||
// other kind of resource management. In this implementation the control block
|
||||
// happens to consist of two atomic words, the reference count (the number
|
||||
// of shared_ptrs that share ownership of the object) and the weak count
|
||||
// (the number of weak_ptrs that observe the object, plus 1 if the
|
||||
// refcount is nonzero).
|
||||
//
|
||||
// The "plus 1" is to prevent a race condition in the shared_ptr and
|
||||
// weak_ptr destructors. We need to make sure the control block is
|
||||
// only deleted once, so we need to make sure that at most one
|
||||
// object sees the weak count decremented from 1 to 0.
|
||||
class SharedPtrControlBlock {
|
||||
template <typename T> friend class shared_ptr;
|
||||
template <typename T> friend class weak_ptr;
|
||||
private:
|
||||
SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
|
||||
Atomic32 refcount_;
|
||||
Atomic32 weak_count_;
|
||||
};
|
||||
|
||||
// Forward declaration. The class is defined below.
|
||||
template <typename T> class enable_shared_from_this;
|
||||
|
||||
template <typename T>
|
||||
class shared_ptr {
|
||||
template <typename U> friend class weak_ptr;
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
shared_ptr() : ptr_(NULL), control_block_(NULL) {}
|
||||
|
||||
explicit shared_ptr(T* ptr)
|
||||
: ptr_(ptr),
|
||||
control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
|
||||
// If p is non-null and T inherits from enable_shared_from_this, we
|
||||
// set up the data that shared_from_this needs.
|
||||
MaybeSetupWeakThis(ptr);
|
||||
}
|
||||
|
||||
// Copy constructor: makes this object a copy of ptr, and increments
|
||||
// the reference count.
|
||||
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.
|
||||
// Increment ptr's reference count and decrement the one being replaced.
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO(austern): Consider providing this constructor. The draft C++ standard
|
||||
// (20.8.10.2.1) includes it. However, it says that this constructor throws
|
||||
// a bad_weak_ptr exception when ptr is expired. Is it better to provide this
|
||||
// constructor and make it do something else, like fail with a CHECK, or to
|
||||
// leave this constructor out entirely?
|
||||
//
|
||||
// template <typename U>
|
||||
// shared_ptr(const weak_ptr<U>& ptr);
|
||||
|
||||
~shared_ptr() {
|
||||
if (ptr_ != NULL) {
|
||||
if (!RefCountDec(&control_block_->refcount_)) {
|
||||
delete ptr_;
|
||||
|
||||
// weak_count_ is defined as the number of weak_ptrs that observe
|
||||
// ptr_, plus 1 if refcount_ is nonzero.
|
||||
if (!RefCountDec(&control_block_->weak_count_)) {
|
||||
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.
|
||||
//
|
||||
// If you have a compilation error with this code, make sure you aren't
|
||||
// passing NULL, nullptr, or 0 to this function. Call reset without an
|
||||
// argument to reset to a null ptr.
|
||||
template <typename Y>
|
||||
void reset(Y* p) {
|
||||
if (p != ptr_) {
|
||||
shared_ptr<T> tmp(p);
|
||||
tmp.swap(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
reset(static_cast<T*>(NULL));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
using std::swap; // http://go/using-std-swap
|
||||
swap(ptr_, r.ptr_);
|
||||
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) {
|
||||
// This performs a static_cast on r.ptr_ to U*, which is a no-op since it
|
||||
// is already a U*. So initialization here requires that r.ptr_ is
|
||||
// implicitly convertible to T*.
|
||||
InitializeWithStaticCast<U>(r);
|
||||
}
|
||||
|
||||
// Initializes *this as described in Initialize, but additionally performs a
|
||||
// static_cast from r.ptr_ (V*) to U*.
|
||||
// NOTE(gfc): We'd need a more general form to support const_pointer_cast and
|
||||
// dynamic_pointer_cast, but those operations are sufficiently discouraged
|
||||
// that supporting static_pointer_cast is sufficient.
|
||||
template <typename U, typename V>
|
||||
void InitializeWithStaticCast(const shared_ptr<V>& r) {
|
||||
if (r.control_block_ != NULL) {
|
||||
RefCountInc(&r.control_block_->refcount_);
|
||||
|
||||
ptr_ = static_cast<U*>(r.ptr_);
|
||||
control_block_ = r.control_block_;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for the constructor that takes a raw pointer. If T
|
||||
// doesn't inherit from enable_shared_from_this<T> then we have nothing to
|
||||
// do, so this function is trivial and inline. The other version is declared
|
||||
// out of line, after the class definition of enable_shared_from_this.
|
||||
void MaybeSetupWeakThis(enable_shared_from_this<T>* ptr);
|
||||
void MaybeSetupWeakThis(...) { }
|
||||
|
||||
T* ptr_;
|
||||
SharedPtrControlBlock* control_block_;
|
||||
|
||||
#ifndef SWIG
|
||||
template <typename U>
|
||||
friend class shared_ptr;
|
||||
|
||||
template <typename U, typename V>
|
||||
friend shared_ptr<U> static_pointer_cast(const shared_ptr<V>& rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& rhs) {
|
||||
shared_ptr<T> lhs;
|
||||
lhs.template InitializeWithStaticCast<T>(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// See comments at the top of the file for a description of why this
|
||||
// class exists, and the draft C++ standard (as of July 2009 the
|
||||
// latest draft is N2914) 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 &&
|
||||
!RefCountDec(&control_block_->weak_count_)) {
|
||||
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) {
|
||||
using std::swap; // http://go/using-std-swap
|
||||
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; }
|
||||
|
||||
// Return a shared_ptr that owns the object we are observing. If we
|
||||
// have expired, the shared_ptr will be empty. We have to be careful
|
||||
// about concurrency, though, since some other thread might be
|
||||
// destroying the last owning shared_ptr while we're in this
|
||||
// function. We want to increment the refcount only if it's nonzero
|
||||
// and get the new value, and we want that whole operation to be
|
||||
// atomic.
|
||||
shared_ptr<T> lock() const {
|
||||
shared_ptr<T> result;
|
||||
if (control_block_ != NULL) {
|
||||
Atomic32 old_refcount;
|
||||
do {
|
||||
old_refcount = control_block_->refcount_;
|
||||
if (old_refcount == 0)
|
||||
break;
|
||||
} while (old_refcount !=
|
||||
NoBarrier_CompareAndSwap(
|
||||
&control_block_->refcount_, old_refcount,
|
||||
old_refcount + 1));
|
||||
if (old_refcount > 0) {
|
||||
result.ptr_ = ptr_;
|
||||
result.control_block_ = control_block_;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
|
||||
ptr_ = ptr;
|
||||
control_block_ = control_block;
|
||||
if (control_block_ != NULL)
|
||||
RefCountInc(&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);
|
||||
}
|
||||
|
||||
// See comments at the top of the file for a description of why this class
|
||||
// exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009
|
||||
// the latest draft is N2914) for the detailed specification.
|
||||
template <typename T>
|
||||
class enable_shared_from_this {
|
||||
friend class shared_ptr<T>;
|
||||
public:
|
||||
// Precondition: there must be a shared_ptr that owns *this and that was
|
||||
// created, directly or indirectly, from a raw pointer of type T*. (The
|
||||
// latter part of the condition is technical but not quite redundant; it
|
||||
// rules out some complicated uses involving inheritance hierarchies.)
|
||||
shared_ptr<T> shared_from_this() {
|
||||
// Behavior is undefined if the precondition isn't satisfied; we choose
|
||||
// to die with a CHECK failure.
|
||||
CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
|
||||
return weak_this_.lock();
|
||||
}
|
||||
shared_ptr<const T> shared_from_this() const {
|
||||
CHECK(!weak_this_.expired()) << "No shared_ptr owns this object";
|
||||
return weak_this_.lock();
|
||||
}
|
||||
|
||||
protected:
|
||||
enable_shared_from_this() { }
|
||||
enable_shared_from_this(const enable_shared_from_this& other) { }
|
||||
enable_shared_from_this& operator=(const enable_shared_from_this& other) {
|
||||
return *this;
|
||||
}
|
||||
~enable_shared_from_this() { }
|
||||
|
||||
private:
|
||||
weak_ptr<T> weak_this_;
|
||||
};
|
||||
|
||||
// This is a helper function called by shared_ptr's constructor from a raw
|
||||
// pointer. If T inherits from enable_shared_from_this<T>, it sets up
|
||||
// weak_this_ so that shared_from_this works correctly. If T does not inherit
|
||||
// from weak_this we get a different overload, defined inline, which does
|
||||
// nothing.
|
||||
template<typename T>
|
||||
void shared_ptr<T>::MaybeSetupWeakThis(enable_shared_from_this<T>* ptr) {
|
||||
if (ptr) {
|
||||
CHECK(ptr->weak_this_.expired()) << "Object already owned by a shared_ptr";
|
||||
ptr->weak_this_ = *this;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GTL_USE_STD_SHARED_PTR
|
||||
|
||||
} // internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__
|
Loading…
Add table
Reference in a new issue