//# CountedPtr.h: Referenced counted pointer classes //# Copyright (C) 1993,1994,1995,1996,1999,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_COUNTEDPTR_H #define CASA_COUNTEDPTR_H #include #include //# Define the old names for backward compatibility. #define SHARED_PTR std::shared_ptr #define DYNAMIC_POINTER_CAST std::dynamic_pointer_cast #define CONST_POINTER_CAST std::const_pointer_cast #define STATIC_POINTER_CAST std::static_pointer_cast namespace casacore { //#Begin casa namespace // act on dereference error // // Global function that throws an exception. It is called by the // member functions of the counted pointer classes when an // un-initialized (null) pointer is followed. // // void throw_Null_CountedPtr_dereference_error(); // // Referenced counted pointer for constant data // // // // This class is Counted because it is reference counted. // // // This class implements a reference counting mechanism. It // allows CountedPtrs to be passed around freely, // incrementing or decrementing the reference count as needed when one // CountedPtr is assigned to another. When the // reference count reaches zero the internal storage is deleted by // default, but this behavior can be overridden. // // Internally the class uses std::shared_ptr to be thread-safe. Note that // tr1 is used if the compiler does not support C++11 yet. // // // Reference counting // template class CountedPtr { protected: // Helper class to make deletion of object optional. template class Deleter { public: Deleter (Bool deleteIt) : reallyDeleteIt_p (deleteIt) {} void operator() (T * data) const { if (reallyDeleteIt_p) delete data;} private: Bool reallyDeleteIt_p; }; public: // This constructor allows for the creation of a null // CountedPtr. The assignment operator can be used // to assign a null CountedPtr from another // pointer. // CountedPtr() : pointerRep_p () {} // This constructor sets up a reference count for the val // pointer. By default, the data pointed to by val // will be deleted when it is no longer referenced. Passing in // False for delit will prevent the data // from being deleted when the reference count reaches zero. // // After the counted pointer is initialized // the value should no longer be manipulated by the raw pointer of // type t*. // CountedPtr(t *val, Bool delit = True) : pointerRep_p (val, Deleter (delit)) {} // This copy constructor allows CountedPtrs to be // initialized from other CountedPtrs for which the pointer TP* // is convertible to T*. template CountedPtr(const CountedPtr& that) : pointerRep_p(that.pointerRep_p) {} // Create from a shared_ptr. CountedPtr (const std::shared_ptr& rep) : pointerRep_p (rep) {} // This destructor only deletes the really stored data when it was // initialized as deletable and the reference count is zero. ~CountedPtr() {} // This assignment operator allows CountedPtrs to be // copied from other CountedPtrs for which the pointer TP* // is convertible to t*. template CountedPtr& operator=(const CountedPtr& that) { pointerRep_p = that.pointerRep_p; return *this; } // Reset the pointer. // void reset (t *val, Bool delit=True) { pointerRep_p = PointerRep (val, Deleter(delit)); } void reset() { pointerRep_p.reset(); } // // The CountedPtr indirection operator simply // returns a reference to the value being protected. If the pointer // is un-initialized (null), an exception will be thrown. The member // function // null() // can be used to catch such a condition in time. // The address of the reference returned should // not be stored for later use. // t &operator*() const { if (null()){ throw_Null_CountedPtr_dereference_error(); } return pointerRep_p.operator* (); } // This dereferencing operator behaves as expected; it returns the // pointer to the value being protected, and then its dereferencing // operator will be invoked as appropriate. If the pointer is // un-initialized (null), an exception will be thrown. The member // function // null() // can be used to catch such a condition in time. t *operator->() const { return get (); } // Get the underlying pointer. t* get () const { return pointerRep_p.get(); } // Equality operator which checks to see if two // CountedPtrs are pointing at the same thing. Bool operator==(const CountedPtr &other) const { return (get() == other.get()); } //# Note: use of const void* gives ambiguius overload error. Bool operator==(int ptr) const { return (ptr == 0 && get() == 0); } // Non-equality operator which checks to see if two // CountedPtrs are not pointing at the same thing. Bool operator!=(const CountedPtr &other) const { return (get() != other.get() ? True : False); } //# Note: use of const void* gives ambiguius overload error. Bool operator!=(int ptr) const { return (ptr != 0 || get() != 0); } // This assignment operator allows the object to which the current // CountedPtr points to be changed. CountedPtr & operator=(t *v) { pointerRep_p = PointerRep (v); return * this; } // Cast functions. // template CountedPtr static_ptr_cast() const { return CountedPtr (std::static_pointer_cast (pointerRep_p)); } template CountedPtr const_ptr_cast() const { return CountedPtr (std::const_pointer_cast (pointerRep_p)); } template CountedPtr dynamic_ptr_cast() const { return CountedPtr (std::dynamic_pointer_cast (pointerRep_p)); } // // Sometimes it is useful to know if there is more than one // reference made. This is a way of getting that. Of course the point // of these classes is that this information is normally not required. uInt nrefs() const { return pointerRep_p.use_count(); } // Check to see if this CountedPtr is // un-initialized, null. Bool null() const { return get() == 0; } // Test if it contains a valid pointer. operator bool() const { return get() != 0; } private: // Make all types of CountedPtr a friend for the templated operator=. template friend class CountedPtr; typedef std::shared_ptr PointerRep; PointerRep pointerRep_p; }; // A shared_ptr is used as implementation. inline Bool countedPtrShared() { return True; } // Cast the CountedPtr from one pointer type to another. template CountedPtr static_pointer_cast (const CountedPtr& that) { return that.template static_ptr_cast(); } template CountedPtr const_pointer_cast (const CountedPtr& that) { return that.template const_ptr_cast(); } template CountedPtr dynamic_pointer_cast (const CountedPtr& that) { return that.template dynamic_ptr_cast(); } } //#End casa namespace #ifndef CASACORE_NO_AUTO_TEMPLATES #include #endif //# CASACORE_NO_AUTO_TEMPLATES #endif