/usr/include/stxxl/bits/common
NameSizeModeActions
addressable_queues.h60360644editdlrm
aligned_alloc.h53870644editdlrm
binary_buffer.h200630644editdlrm
cmdline.h234820644editdlrm
condition_variable.h21410644editdlrm
counting_ptr.h164040644editdlrm
error_handling.h77020644editdlrm
exceptions.h20000644editdlrm
exithandler.h14000644editdlrm
external_shared_ptr.h37600644editdlrm
is_sorted.h18180644editdlrm
log.h12650644editdlrm
mutex.h33320644editdlrm
new_alloc.h39010644editdlrm
onoff_switch.h21460644editdlrm
rand.h81910644editdlrm
seed.h8630644editdlrm
semaphore.h24490644editdlrm
settings.h9710644editdlrm
simple_vector.h46390644editdlrm
state.h16870644editdlrm
timer.h46620644editdlrm
tmeta.h29880644editdlrm
tuple.h195530644editdlrm
types.h19230644editdlrm
uint_types.h95720644editdlrm
utils.h83800644editdlrm
Edit: /usr/include/stxxl/bits/common/counting_ptr.h (16404B)
/*************************************************************************** * include/stxxl/bits/common/counting_ptr.h * * Part of the STXXL. See http://stxxl.sourceforge.net * * Copyright (C) 2010-2011 Raoul Steffen * Copyright (C) 2013 Timo Bingmann * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) **************************************************************************/ #ifndef STXXL_COMMON_COUNTING_PTR_HEADER #define STXXL_COMMON_COUNTING_PTR_HEADER #include #include #include #include #include #include STXXL_BEGIN_NAMESPACE //! \addtogroup support //! \{ /*! * High-performance smart pointer used as a wrapping reference counting * pointer. * * This smart pointer class requires two functions in the templated type: void * inc_reference() and void dec_reference(). These must increment and decrement * a reference counter inside the templated object. When initialized, the type * must have reference count zero. It is _not_ immediately called with * add_reference(). Each new object referencing the data calls add_reference() * and each destroying holder calls del_reference(). When the data object * determines that it's internal counter is zero, then it must destroy itself. * * Accompanying the counting_ptr is a const_counting_ptr and a class * counted_object, from which reference counted classes must be derive * from. The class counted_object implement all methods required for reference * counting. * * The whole method is more similar to boost' instrusive_ptr, but also yields * something resembling shared_ptr. */ template class counting_ptr { public: //! contained type. typedef Type element_type; private: //! the pointer to the currently referenced object. Type* m_ptr; protected: //! increment reference counter for current object. void inc_reference() { inc_reference(m_ptr); } //! increment reference counter of other object. void inc_reference(Type* o) { if (o) o->inc_reference(); } //! decrement reference counter of current object and maybe delete it. void dec_reference() { if (m_ptr && m_ptr->dec_reference()) delete m_ptr; } public: //! default constructor: contains a NULL pointer. counting_ptr() : m_ptr(NULL) { } //! constructor with pointer: initializes new reference to ptr. counting_ptr(Type* ptr) : m_ptr(ptr) { inc_reference(); } //! copy-constructor: also initializes new reference to ptr. counting_ptr(const counting_ptr& other_ptr) : m_ptr(other_ptr) { inc_reference(); } //! assignment operator: dereference current object and acquire reference on new one. counting_ptr& operator = (const counting_ptr& other_ptr) { return operator = (other_ptr.m_ptr); } //! assignment to pointer: dereference current and acquire reference to new ptr. counting_ptr& operator = (Type* ptr) { inc_reference(ptr); dec_reference(); m_ptr = ptr; return *this; } //! destructor: decrements reference counter in ptr. ~counting_ptr() { dec_reference(); } //! return the enclosed object as reference. Type& operator * () const { assert(m_ptr); return *m_ptr; } //! return the enclosed pointer. Type* operator -> () const { assert(m_ptr); return m_ptr; } //! implicit cast to the enclosed pointer. operator Type* () const { return m_ptr; } //! return the enclosed pointer. Type * get() const { return m_ptr; } //! test equality of only the pointer values. bool operator == (const counting_ptr& other_ptr) const { return m_ptr == other_ptr.m_ptr; } //! test inequality of only the pointer values. bool operator != (const counting_ptr& other_ptr) const { return m_ptr != other_ptr.m_ptr; } //! cast to bool check for a NULL pointer operator bool () const { return valid(); } //! test for a non-NULL pointer bool valid() const { return (m_ptr != NULL); } //! test for a NULL pointer bool empty() const { return (m_ptr == NULL); } //! if the object is referred by this counting_ptr only bool unique() const { return m_ptr && m_ptr->unique(); } //! make and refer a copy if the original object was shared. void unify() { if (m_ptr && ! m_ptr->unique()) operator = (new Type(*m_ptr)); } //! swap enclosed object with another counting pointer (no reference counts need change) void swap(counting_ptr& b) { std::swap(m_ptr, b.m_ptr); } }; //! swap enclosed object with another counting pointer (no reference counts need change) template void swap(counting_ptr& a1, counting_ptr& a2) { a1.swap(a2); } /*! * High-performance smart pointer used as a wrapping reference counting * pointer. * * This smart pointer class requires two functions in the templated type: void * inc_reference() and void dec_reference(). These must increment and decrement * a reference counter inside the templated object. When initialized, the type * must have reference count zero. It is _not_ immediately called with * add_reference(). Each new object referencing the data calls add_reference() * and each destroying holder calls del_reference(). When the data object * determines that it's internal counter is zero, then it must destroy itself. * * Accompanying the counting_ptr is a const_counting_ptr and a class * counted_object, from which reference counted classes must be derive * from. The class counted_object implement all methods required for reference * counting. * * The whole method is more similar to boost' instrusive_ptr, but also yields * something resembling shared_ptr. */ template class const_counting_ptr { public: //! contained type. typedef Type element_type; private: //! the pointer to the currently referenced object. const Type* m_ptr; protected: //! increment reference counter for current object. void inc_reference() { inc_reference(m_ptr); } //! increment reference counter of other object. void inc_reference(const Type* o) { if (o) o->inc_reference(); } //! decrement reference counter of current object and maybe delete it. void dec_reference() { if (m_ptr && m_ptr->dec_reference()) delete m_ptr; } public: //! default constructor: contains a NULL pointer. const_counting_ptr() : m_ptr(NULL) { } //! constructor with pointer: initializes new reference to ptr. const_counting_ptr(const Type* ptr) : m_ptr(ptr) { inc_reference(); } //! copy-constructor: also initializes new reference to ptr. const_counting_ptr(const const_counting_ptr& other_ptr) : m_ptr(other_ptr) { inc_reference(); } //! constructor from non-const: also initializes new reference to ptr. const_counting_ptr(const counting_ptr& other_ptr) : m_ptr(other_ptr.get()) { inc_reference(); } //! assignment operator: dereference current object and acquire reference on new one. const_counting_ptr& operator = (const const_counting_ptr& other_ptr) { return operator = (other_ptr.m_ptr); } //! assignment operator: dereference current object and acquire reference on new one. const_counting_ptr& operator = (const counting_ptr& other_ptr) { return operator = (other_ptr.get()); } //! assignment to pointer: dereference current and acquire reference to new ptr. const_counting_ptr& operator = (const Type* ptr) { inc_reference(ptr); dec_reference(); m_ptr = ptr; return *this; } //! destructor: decrements reference counter in ptr. ~const_counting_ptr() { dec_reference(); } //! return the enclosed object as reference. const Type& operator * () const { assert(m_ptr); return *m_ptr; } //! return the enclosed pointer. const Type* operator -> () const { assert(m_ptr); return m_ptr; } //! implicit cast to the enclosed pointer. operator const Type* () const { return m_ptr; } //! return the enclosed pointer. const Type * get() const { return m_ptr; } //! test equality of only the pointer values. bool operator == (const const_counting_ptr& other_ptr) const { return m_ptr == other_ptr.m_ptr; } //! test inequality of only the pointer values. bool operator != (const const_counting_ptr& other_ptr) const { return m_ptr != other_ptr.m_ptr; } //! test equality of only the pointer values. bool operator == (const counting_ptr& other_ptr) const { return m_ptr == other_ptr.get(); } //! test inequality of only the pointer values. bool operator != (const counting_ptr& other_ptr) const { return m_ptr != other_ptr.get(); } //! cast to bool check for a NULL pointer operator bool () const { return m_ptr; } //! test for a non-NULL pointer bool valid() const { return m_ptr; } //! test for a NULL pointer bool empty() const { return !m_ptr; } //! if the object is referred by this const_counting_ptr only bool unique() const { return m_ptr && m_ptr->unique(); } //! swap enclosed object with another const_counting pointer (no reference counts need change) void swap(const_counting_ptr& b) { std::swap(m_ptr, b.m_ptr); } }; //! swap enclosed object with another const_counting pointer (no reference counts need change) template void swap(const_counting_ptr& a1, const_counting_ptr& a2) { a1.swap(a2); } /*! * Provides reference counting abilities for use with counting_ptr. * * Use as superclass of the actual object, this adds a reference_count * value. Then either use counting_ptr as pointer to manage references and * deletion, or just do normal new and delete. * * For thread-safe functions, use atomic_counted_object instead of this class! */ class counted_object { private: //! the reference count is kept mutable to all const_counting_ptr() to //! change the reference count. mutable unsigned_type m_reference_count; public: //! new objects have zero reference count counted_object() : m_reference_count(0) { } //! coping still creates a new object with zero reference count counted_object(const counted_object&) : m_reference_count(0) { } //! assignment operator, leaves pointers unchanged counted_object& operator = (const counted_object&) { return *this; } // changing the contents leaves pointers unchanged ~counted_object() { assert(m_reference_count == 0); } public: //! Call whenever setting a pointer to the object void inc_reference() const { ++m_reference_count; } //! Call whenever resetting (i.e. overwriting) a pointer to the object. //! IMPORTANT: In case of self-assignment, call AFTER inc_reference(). //! \return if the object has to be deleted (i.e. if it's reference count dropped to zero) bool dec_reference() const { return (! --m_reference_count); } //! Test if the counted_object is referenced by only one counting_ptr. bool unique() const { return (m_reference_count == 1); } //! Return the number of references to this object (for debugging) unsigned_type get_reference_count() const { return m_reference_count; } }; #if STXXL_HAVE_SYNC_ADD_AND_FETCH || STXXL_MSVC /*! * Provides reference counting abilities for use with counting_ptr with atomics * operations. * * Use as superclass of the actual object, this adds a reference_count * value. Then either use counting_ptr as pointer to manage references and * deletion, or just do normal new and delete. * * This class does thread-safe increment and decrement using atomic operations * on an integral type. */ class atomic_counted_object { private: //! the reference count is kept mutable to all const_counting_ptr() to //! change the reference count. #if STXXL_MSVC mutable long m_reference_count; #else mutable unsigned_type m_reference_count; #endif public: //! new objects have zero reference count atomic_counted_object() : m_reference_count(0) { } //! coping still creates a new object with zero reference count atomic_counted_object(const atomic_counted_object&) : m_reference_count(0) { } //! assignment operator, leaves pointers unchanged atomic_counted_object& operator = (const atomic_counted_object&) { return *this; } // changing the contents leaves pointers unchanged ~atomic_counted_object() { assert(m_reference_count == 0); } public: //! Call whenever setting a pointer to the object void inc_reference() const { #if STXXL_MSVC _InterlockedIncrement(&m_reference_count); #else __sync_add_and_fetch(&m_reference_count, +1); #endif } //! Call whenever resetting (i.e. overwriting) a pointer to the object. //! IMPORTANT: In case of self-assignment, call AFTER inc_reference(). //! \return if the object has to be deleted (i.e. if it's reference count dropped to zero) bool dec_reference() const { #if STXXL_MSVC return (_InterlockedDecrement(&m_reference_count) == 0); #else return (__sync_add_and_fetch(&m_reference_count, -1) == 0); #endif } //! Test if the counted_object is referenced by only one counting_ptr. bool unique() const { return (m_reference_count == 1); } //! Return the number of references to this object (for debugging) unsigned_type get_reference_count() const { return m_reference_count; } }; #else // no atomic intrinsics found, use mutexes (slow) /*! * Provides reference counting abilities for use with counting_ptr with mutex * locking. * * Use as superclass of the actual object, this adds a reference_count * value. Then either use counting_ptr as pointer to manage references and * deletion, or just do normal new and delete. * * This class does thread-safe increment and decrement using scoped locks. A * faster version of this class is available using atomic operations. */ class atomic_counted_object { private: //! the reference count is kept mutable to all const_counting_ptr() to //! change the reference count. mutable unsigned_type m_reference_count; //! the mutex used to synchronize access to the reference counter. mutable mutex m_reference_count_mutex; public: //! new objects have zero reference count atomic_counted_object() : m_reference_count(0) { } //! coping still creates a new object with zero reference count atomic_counted_object(const atomic_counted_object&) : m_reference_count(0) { } //! assignment operator, leaves pointers unchanged atomic_counted_object& operator = (const atomic_counted_object&) { return *this; } // changing the contents leaves pointers unchanged ~atomic_counted_object() { assert(m_reference_count == 0); } public: //! Call whenever setting a pointer to the object void inc_reference() const { scoped_mutex_lock lock(m_reference_count_mutex); ++m_reference_count; } //! Call whenever resetting (i.e. overwriting) a pointer to the object. //! IMPORTANT: In case of self-assignment, call AFTER inc_reference(). //! \return if the object has to be deleted (i.e. if it's reference count dropped to zero) bool dec_reference() const { scoped_mutex_lock lock(m_reference_count_mutex); return (--m_reference_count == 0); } //! Test if the counted_object is referenced by only one counting_ptr. bool unique() const { scoped_mutex_lock lock(m_reference_count_mutex); return (m_reference_count == 1); } //! Return the number of references to this object (for debugging) unsigned_type get_reference_count() const { scoped_mutex_lock lock(m_reference_count_mutex); return m_reference_count; } }; #endif //! \} STXXL_END_NAMESPACE #endif // !STXXL_COMMON_COUNTING_PTR_HEADER