libcwd: The C++ Debugging Support Library - Reference Manual
Author: Carlo Wood
Description: C++ debugging support library with ostream debug output
Keywords: libcwd, debug output, debug facility, debug channel, object orientation, OO, C++, nested debug output, ostream, memory allocation, debugging, source file and line number

Main Page Reference Manual Namespace List Compound List Namespace Members Compound Members File Members

# libcwd/lockable_auto_ptr.h

Go to the documentation of this file.

    00001 // $Header$
    00002 //
    00003 // Copyright (C) 2000 - 2004, by
    00004 //
    00005 // Carlo Wood, Run on IRC <carlo@alinoe.com>
    00006 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
    00007 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
    00008 //
    00009 // This file may be distributed under the terms of the Q Public License
    00010 // version 1.0 as appearing in the file LICENSE.QPL included in the
    00011 // packaging of this file.
    00012 //
    00013
    00018 #ifndef LIBCWD_LOCKABLE_AUTO_PTR_H
    00019 #define LIBCWD_LOCKABLE_AUTO_PTR_H
    00020
    00021 // This header file is really part of libcw, and must be allowed to be used
    00022 // without that libcwd installed or used.
    00023 #ifndef CWDEBUG
    00024 #ifndef LIBCWD_ASSERT
    00025 #define LIBCWD_ASSERT(x)
    00026 #endif
    00027 #else // CWDEBUG
    00028 #ifndef LIBCWD_PRIVATE_ASSERT_H
    00029 #include <libcwd/private_assert.h>
    00030 #endif
    00031 #endif // CWDEBUG
    00032
    00033 namespace libcwd {
    00034
    00035 //===================================================================================================
    00036 // class lockable_auto_ptr
    00037 //
    00038 // An 'auto_ptr' with lockable ownership.
    00039 //
    00040 // When the `lockable_auto_ptr' is not locked it behaves the same as
    00041 // an 'auto_ptr': Ownership of the object it points to is transfered
    00042 // when the `lockable_auto_ptr' is copied or assigned to another
    00043 // `lockable_auto_ptr'.  The object it points to is deleted when the
    00044 // `lockable_auto_ptr' that owns it is destructed.
    00045 //
    00046 // When the `lockable_auto_ptr' is locked, then the ownership is
    00047 // not transfered, but stays on the same (locked) `lockable_auto_ptr'.
    00048 //
    00049
    00050 template<class X, bool array = false>   // Use array == true when `ptr' was allocated with new [].
    00051   class lockable_auto_ptr {
    00052     typedef X element_type;
    00053
    00054     private:
    00055     template<class Y, bool ARRAY> friend class lockable_auto_ptr;
    00056     X* ptr;             // Pointer to object of type X, or NULL when not pointing to anything.
    00057     bool locked;        // Set if this lockable_auto_ptr object is locked.
    00058     mutable bool owner; // Set if this lockable_auto_ptr object is the owner of the object that
    00059                         // `ptr' points too.
    00060
    00061   public:
    00062     //-----------------------------------------------------------------------------------------------
    00063     // Constructors
    00064     //
    00065
    00066     explicit lockable_auto_ptr(X* p = 0) : ptr(p), locked(false), owner(p) { }
    00067         // Explicit constructor that creates a lockable_auto_ptr pointing to `p'.
    00068
    00069     lockable_auto_ptr(lockable_auto_ptr const& r) :
    00070         ptr(r.ptr), locked(false), owner(r.owner && !r.locked)
    00071         { if (!r.locked) r.owner = 0; }
    00072         // The default copy constructor.
    00073
    00074     template<class Y>
    00075       lockable_auto_ptr(lockable_auto_ptr<Y, array> const& r) :
    00076           ptr(r.ptr), locked(false), owner(r.owner && !r.locked)
    00077           { if (!r.locked) r.owner = 0; }
    00078         // Constructor to copy a lockable_auto_ptr that point to an object derived from X.
    00079
    00080     //-----------------------------------------------------------------------------------------------
    00081     // Operators
    00082     //
    00083
    00084     template<class Y>
    00085     lockable_auto_ptr& operator=(lockable_auto_ptr<Y, array> const& r);
    00086
    00087     lockable_auto_ptr& operator=(lockable_auto_ptr const& r) { return operator= <X> (r); }
    00088         // The default assignment operator.
    00089
    00090     //-----------------------------------------------------------------------------------------------
    00091     // Destructor
    00092     //
    00093
    00094     ~lockable_auto_ptr() { if (owner) { if (array) delete [] ptr; else delete ptr; } }
    00095
    00096     //-----------------------------------------------------------------------------------------------
    00097     // Accessors
    00098     //
    00099
    00100     X& operator*() const { return *ptr; }
    00101       // Access the object that this `lockable_auto_ptr' points to.
    00102
    00103     X* operator->() const { return ptr; }
    00104       // Access the object that this `lockable_auto_ptr' points to.
    00105
    00106     X* get() const { return ptr; }
    00107       // Return the pointer itself.
    00108
    00109     bool strict_owner() const { LIBCWD_ASSERT(is_owner()); return locked; }
    00110       // Returns `true' when this object is the strict owner.
    00111       // You should only call this when this object is the owner.
    00112
    00113 #ifdef CWDEBUG
    00114     bool is_owner(void) const { return owner; }
    00115       // Don't use this except for debug testing.
    00116 #endif
    00117
    00118     //-----------------------------------------------------------------------------------------------
    00119     // Manipulators
    00120     //
    00121
    00122     void reset()
    00123     {
    00124       bool owns = owner;
    00125       owner = 0;
    00126       if (owns)
    00127       {
    00128         if (array)
    00129           delete [] ptr;
    00130         else
    00131           delete ptr;
    00132       }
    00133       ptr = NULL;
    00134     }
    00135       // Get rid of object, if any.
    00136
    00137     X* release() const { LIBCWD_ASSERT(is_owner()); owner = 0; return ptr; }
    00138       // Release this object of its ownership (the caller is now responsible for deleting it if
    00139       // this object was the owner).  You should only call this when this object is the owner.
    00140
    00141     void lock() { LIBCWD_ASSERT(is_owner()); locked = true; }
    00142       // Lock the ownership.
    00143       // You should only call this when this object is the owner.
    00144
    00145     void unlock() { locked = false; }
    00146       // Unlock the ownership (if any).
    00147   };
    00148
    00149 template<class X, bool array>
    00150   template<class Y>
    00151     lockable_auto_ptr<X, array>&
    00152     lockable_auto_ptr<X, array>::operator=(lockable_auto_ptr<Y, array> const& r)
    00153     {
    00154       if ((void*)&r != (void*)this)
    00155       {
    00156         if (owner)
    00157         {
    00158           if (array)
    00159             delete [] ptr;
    00160           else
    00161             delete ptr;
    00162         }
    00163         ptr = r.ptr;
    00164         if (r.locked)
    00165           owner = 0;
    00166         else
    00167         {
    00168           owner = r.owner;
    00169           r.owner = 0;
    00170         }
    00171       }
    00172       return *this;
    00173     }
    00174
    00175 } // namespace libcwd
    00176
    00177 #endif // LIBCWD_LOCKABLE_AUTO_PTR_H