Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/common/shared_object.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2010-2011 Raoul Steffen <R-Steffen@gmx.de> 00007 * 00008 * Distributed under the Boost Software License, Version 1.0. 00009 * (See accompanying file LICENSE_1_0.txt or copy at 00010 * http://www.boost.org/LICENSE_1_0.txt) 00011 **************************************************************************/ 00012 00013 #ifndef STXXL_SHARED_OBJECT_HEADER 00014 #define STXXL_SHARED_OBJECT_HEADER 00015 00016 #include <cassert> 00017 #include <stxxl/bits/namespace.h> 00018 00019 __STXXL_BEGIN_NAMESPACE 00020 00021 //! \brief Behaves much like a Pointer, plus deleteing the referred object with it's last reference 00022 //! and ability to unify, i.e. make and refer a copy if the original object was shared. 00023 //! 00024 //! Use with objects derived from shared_object. 00025 //! Similar to boost/shared_ptr. 00026 template <class C> 00027 class shared_object_pointer 00028 { 00029 C * ptr; 00030 00031 void new_reference() 00032 { new_reference(ptr); } 00033 00034 void new_reference(C * o) 00035 { if (o) o->new_reference(); } 00036 00037 void delete_reference() 00038 { if (ptr && ptr->delete_reference()) delete ptr; } 00039 00040 public: 00041 shared_object_pointer() 00042 : ptr(0) {} 00043 00044 shared_object_pointer(C * pointer) 00045 : ptr(pointer) 00046 { new_reference(); } 00047 00048 shared_object_pointer(const shared_object_pointer & shared_pointer) 00049 : ptr(shared_pointer.ptr) 00050 { new_reference(); } 00051 00052 shared_object_pointer & operator = (const shared_object_pointer & shared_pointer) 00053 { return operator = (shared_pointer.ptr); } 00054 00055 shared_object_pointer & operator = (C * pointer) 00056 { 00057 new_reference(pointer); 00058 delete_reference(); 00059 ptr = pointer; 00060 return *this; 00061 } 00062 00063 ~shared_object_pointer() 00064 { delete_reference(); } 00065 00066 C & operator * () const 00067 { 00068 assert (ptr); 00069 return *ptr; 00070 } 00071 00072 C * operator -> () const 00073 { 00074 assert(ptr); 00075 return ptr; 00076 } 00077 00078 operator C * () const 00079 { return ptr; } 00080 00081 C * get() const 00082 { return ptr; } 00083 00084 bool operator == (const shared_object_pointer & shared_pointer) const 00085 { return ptr == shared_pointer.ptr; } 00086 00087 operator bool () const 00088 { return ptr; } 00089 00090 bool valid() const 00091 { return ptr; } 00092 00093 bool empty() const 00094 { return ! ptr; } 00095 00096 //! \brief if the object is referred by this shared_object_pointer only 00097 bool unique() const 00098 { return ptr && ptr->unique(); } 00099 00100 //! \brief Make and refer a copy if the original object was shared. 00101 void unify() 00102 { 00103 if (ptr && ! ptr->unique()) 00104 operator = (new C(*ptr)); 00105 } 00106 }; 00107 00108 //! \brief Behaves much like a Pointer, plus deleteing the referred object with it's last reference 00109 //! and ability to unify, i.e. make and refer a copy if the original object was shared. 00110 //! 00111 //! Use with objects derived from shared_object. 00112 //! Similar to boost/shared_ptr. 00113 template <class C> 00114 class const_shared_object_pointer 00115 { 00116 const C * ptr; 00117 00118 void new_reference() 00119 { new_reference(ptr); } 00120 00121 void new_reference(const C * o) 00122 { if (o) o->new_reference(); } 00123 00124 void delete_reference() 00125 { if (ptr && ptr->delete_reference()) delete ptr; } 00126 00127 public: 00128 const_shared_object_pointer(const shared_object_pointer<C> & shared_pointer) 00129 : ptr(shared_pointer.ptr) 00130 { new_reference(); } 00131 00132 const_shared_object_pointer() 00133 : ptr(0) {} 00134 00135 const_shared_object_pointer(const C * pointer) 00136 : ptr(pointer) 00137 { new_reference(); } 00138 00139 const_shared_object_pointer(const const_shared_object_pointer & shared_pointer) 00140 : ptr(shared_pointer.ptr) 00141 { new_reference(); } 00142 00143 const_shared_object_pointer & operator = (const const_shared_object_pointer & shared_pointer) 00144 { return operator = (shared_pointer.ptr); } 00145 00146 const_shared_object_pointer & operator = (const C * pointer) 00147 { 00148 new_reference(pointer); 00149 delete_reference(); 00150 ptr = pointer; 00151 return *this; 00152 } 00153 00154 ~const_shared_object_pointer() 00155 { delete_reference(); } 00156 00157 const C & operator * () const 00158 { 00159 assert (ptr); 00160 return *ptr; 00161 } 00162 00163 const C * operator -> () const 00164 { 00165 assert(ptr); 00166 return ptr; 00167 } 00168 00169 operator const C * () const 00170 { return ptr; } 00171 00172 const C * get() const 00173 { return ptr; } 00174 00175 bool operator == (const const_shared_object_pointer & shared_pointer) const 00176 { return ptr == shared_pointer.ptr; } 00177 00178 operator bool () const 00179 { return ptr; } 00180 00181 bool valid() const 00182 { return ptr; } 00183 00184 bool empty() const 00185 { return ! ptr; } 00186 00187 //! \brief if the object is referred by this shared_object_pointer only 00188 bool unique() const 00189 { return ptr && ptr->unique(); } 00190 }; 00191 00192 //! \brief Provides reference counting abilities for use with shared_object_pointer. 00193 //! 00194 //! Use as superclass of the actual object. Then either use shared_object_pointer as pointer 00195 //! to manage references and deletion, or just do normal new and delete. 00196 class shared_object 00197 { 00198 mutable int reference_count; 00199 00200 public: 00201 shared_object() 00202 : reference_count(0) {} // new objects have no reference 00203 00204 shared_object(const shared_object &) 00205 : reference_count(0) {} // coping still creates a new object 00206 00207 const shared_object & operator = (const shared_object &) const 00208 { return *this; } // changing the contents leaves pointers unchanged 00209 00210 shared_object & operator = (const shared_object &) 00211 { return *this; } // changing the contents leaves pointers unchanged 00212 00213 ~shared_object() 00214 { assert (! reference_count); } 00215 00216 private: 00217 template <class C> friend class shared_object_pointer; 00218 00219 //! \brief Call whenever setting a pointer to the object 00220 void new_reference() const 00221 { ++reference_count; } 00222 00223 //! \brief Call whenever resetting (i.e. overwriting) a pointer to the object. 00224 //! IMPORTANT: In case of self-assignment, call AFTER new_reference(). 00225 //! \return if the object has to be deleted (i.e. if it's reference count dropped to zero) 00226 bool delete_reference() const 00227 { return (! --reference_count); } 00228 00229 //! \brief if the shared_object is referenced by only one shared_object_pointer 00230 bool unique() const 00231 { return reference_count == 1; } 00232 }; 00233 00234 __STXXL_END_NAMESPACE 00235 00236 #endif // STXXL_SHARED_OBJECT_HEADER