Stxxl  1.4.0
include/stxxl/bits/common/shared_object.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines