// bslma_sharedptroutofplacerep.h -*-C++-*- #ifndef INCLUDED_BSLMA_SHAREDPTROUTOFPLACEREP #define INCLUDED_BSLMA_SHAREDPTROUTOFPLACEREP #include <bsls_ident.h> BSLS_IDENT("$Id$ $CSID$") //@PURPOSE: Provide an out-of-place implementation of 'bslma::SharedPtrRep'. // //@CLASSES: // bslma::SharedPtrOutofplaceRep: out-of-place shared pointer implementation // //@SEE_ALSO: bslma_sharedptr, bslma_sharedptrrep, bslma_sharedptrinplacerep // //@DESCRIPTION: This component provides a concrete implementation of // 'bslma::SharedPtrRep' for managing objects of the parameterized 'TYPE' that // are stored outside of the representation. When all references to the // out-of-place object are released using 'releaseRef', the deleter of the // parameterized 'DELETER' type is invoked to delete the shared object. // ///Thread Safety ///------------- // 'bslma::SharedPtrOutofplaceRep' is thread-safe provided that 'disposeObject' // and 'disposeRep' are not called explicitly, meaning that all non-creator // operations other than 'disposeObject' and 'disposeRep' on a given instance // can be safely invoked simultaneously from multiple threads ('disposeObject' // and 'disposeRep' are meant to be invoked only by 'releaseRef' and // 'releaseWeakRef'). Note that there is no thread safety guarantees for // operations on the managed object. // ///Deleters ///-------- // When the last shared reference to a shared object is released, the object is // destroyed using the "deleter" provided when the associated shared pointer // representation was created. 'bslma::SharedPtrOutofplaceRep' supports two // kinds of "deleter" objects, which vary in how they are invoked. A // "function-like" deleter is any language entity that can be invoked such that // the expression 'deleterInstance(objectPtr)' is a valid expression, and a // "factory" deleter is any language entity that can be invoked such that the // expression 'deleterInstance.deleteObject(objectPtr)' is a valid expression, // where 'deleterInstance' is an instance of the "deleter" object, and // 'objectPtr' is a pointer to the shared object. In summary: //.. // Deleter Expression used to destroy 'objectPtr' // - - - - - - - - - - - - - - - - - - - - - - - - - - - // "function-like" deleterInstance(objectPtr); // "factory" deleterInstance.deleteObject(objectPtr); //.. // The following are examples of function-like deleters that delete an object // of 'MyType': //.. // void deleteObject(MyType *object); // // Delete the specified 'object'. // // void releaseObject(MyType *object); // // Release the specified 'object'. // // struct FunctionLikeDeleterObject { // // This 'struct' provides an 'operator()' that can be used to delete a // // 'MyType' object. // // void operator()(MyType *object); // // Destroy the specified 'object'. // }; //.. // The following on the other hand is an example of a factory deleter: //.. // class MyFactory { // // // . . . // // // MANIPULATORS // MyType *createObject(bslma::Allocator *basicAllocator = 0); // // Create a 'MyType' object. Optionally specify a // // 'basicAllocator' used to supply memory. If 'basicAllocator' is // // 0, the currently installed default allocator is used. // // void deleteObject(MyType *object); // // Delete the specified 'object'. // }; //.. // Note that 'deleteObject' is provided by all 'bslma' allocators and by any // object that implements the 'bdlma::Deleter' protocol. Thus, any of these // objects can be used as a factory deleter. The purpose of this design is to // allow 'bslma' allocators and factories to be used seamlessly as deleters. // // The selection of which expression is used by 'bslma::SharedPtrOutofplaceRep' // to destroy a shared object is based on how the deleter is passed to the // shared pointer object: Deleters that are passed by *address* are assumed to // be factory deleters, while those that are passed by *value* are assumed to // be function-like. Note that if the wrong interface is used for a deleter, // i.e., if a function-like deleter is passed by pointer, or a factory deleter // is passed by value, and the expression used to delete the object is invalid, // a compiler diagnostic will be emitted indicating the error. // ///Usage ///----- // The following example demonstrates how to implement a shared // 'bdlt::Datetime' object using 'bslma::SharedPtrOutofplaceRep': //.. // class MySharedDatetimePtr { // // This class provide a reference counted smart pointer to support // // shared ownership of a 'bdlt::Datetime' object. // // private: // bdlt::Datetime *d_ptr_p; // pointer to the managed object // bslma::SharedPtrRep *d_rep_p; // pointer to the representation object // // private: // // NOT IMPLEMENTED // MySharedDatetimePtr& operator=(const MySharedDatetimePtr&); // // public: // // CREATORS // MySharedDatetimePtr(bdlt::Datetime *ptr, // bslma::Allocator *basicAllocator = 0); // // Create a 'MySharedDatetimePtr' object to managed the specified // // 'ptr'. Optionally specify an 'basicAllocator' to allocate and // // deallocate the internal representation and to destroy 'ptr' when // // all references have been released. The behavior is undefined // // unless 'ptr' was allocated using memory supplied by // // 'basicAllocator'. // // MySharedDatetimePtr(const MySharedDatetimePtr& original); // // Create a shared datetime that refers to the same object managed // // by the specified 'original' // // ~MySharedDatetimePtr(); // // Destroy this shared datetime and release the reference to the // // 'bdlt::Datetime' object to which it might be referring. If this // // is the last shared reference, deleted the managed object. // // // MANIPULATORS // bdlt::Datetime& operator*() const; // // Return a reference offering modifiable access to the shared // // datetime. // // bdlt::Datetime *operator->() const; // // Return the address of the modifiable 'bdlt::Datetime' to which // // this object refers. // // bdlt::Datetime *ptr() const; // // Return the address of the modifiable 'bdlt::Datetime' to which // // this object refers. // }; //.. // Finally, we define the implementation. //.. // MySharedDatetimePtr::MySharedDatetimePtr(bdlt::Datetime *ptr, // bslma::Allocator *basicAllocator) // { // d_ptr_p = ptr; // d_rep_p = // bslma::SharedPtrOutofplaceRep<bdlt::Datetime, bslma::Allocator *>:: // makeOutofplaceRep(ptr, basicAllocator, basicAllocator); // } // // MySharedDatetimePtr::MySharedDatetimePtr( // const MySharedDatetimePtr& original) // : d_ptr_p(original.d_ptr_p) // , d_rep_p(original.d_rep_p) // { // if (d_ptr_p) { // d_rep_p->acquireRef(); // } else { // d_rep_p = 0; // } // } // // MySharedDatetimePtr::~MySharedDatetimePtr() // { // if (d_rep_p) { // d_rep_p->releaseRef(); // } // } // // bdlt::Datetime& MySharedDatetimePtr::operator*() const { // return *d_ptr_p; // } // // bdlt::Datetime *MySharedDatetimePtr::operator->() const { // return d_ptr_p; // } // // bdlt::Datetime *MySharedDatetimePtr::ptr() const { // return d_ptr_p; // } //.. #include <bslscm_version.h> #include <bslma_allocator.h> #include <bslma_default.h> #include <bslma_sharedptrrep.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_allocatorargt.h> #include <bslmf_conditional.h> #include <bslmf_functionpointertraits.h> #include <bslmf_integralconstant.h> #include <bslmf_isconvertible.h> #include <bslmf_isfunction.h> #include <bslmf_ispointer.h> #include <bslmf_issame.h> #include <bslmf_usesallocatorargt.h> #include <bsls_util.h> #include <typeinfo> namespace BloombergLP { namespace bslma { template <class TYPE, class DELETER> struct SharedPtrOutofplaceRep_InitProctor; struct SharedPtrOutofplaceRep_DeleterHelper; struct SharedPtrOutofplaceRep_DeleterType; template <class DELETER> class SharedPtrOutofplaceRep_DeleterDiscriminator; // ========================================= // struct SharedPtrOutofplaceRep_DeleterType // ========================================= struct SharedPtrOutofplaceRep_DeleterType { // This 'struct' enumerates four kinds of deleters, the first two are // factory deleters, and the last two are function-like deleters. enum { // Enumeration used to discriminate among the different deleters. BSLMA_ALLOCATOR_PTR = 0, // Used to indicate that a deleter is a // pointer that follows the 'Allocator' // protocol. BSLMA_FACTORY_PTR = 1, // Used to indicate that a deleter is a // pointer to a factory object that // implements the 'deleteObject' protocol. BSLMA_FUNCTOR_WITH_ALLOC = 2,// Used to indicate that a deleter is a // functor that takes an allocator at // construction. BSLMA_FUNCTOR_WITH_ALLOC_ARG_T = 3, // Used to indicate that a deleter is a // functor that takes an allocator at // construction using the // 'bsl::allocator_arg' idiom. BSLMA_FUNCTOR_WITHOUT_ALLOC = 4 // Used to indicate that a deleter is a // functor that does not take an allocator // at construction. }; }; // ============================ // class SharedPtrOutofplaceRep // ============================ template <class TYPE, class DELETER> class SharedPtrOutofplaceRep : public SharedPtrRep { // This class provides a concrete implementation of the 'SharedPtrRep' // protocol for out-of-place instances of the parameterized 'TYPE'. Upon // destruction of this object, the parameterized 'DELETER' type is invoked // on the pointer to the shared object. // PRIVATE TYPES typedef SharedPtrOutofplaceRep_DeleterType DeleterType; // 'DeleterType' is an alias for the 'struct' that defines the types of // deleter used to destroy the shared object. typedef typename SharedPtrOutofplaceRep_DeleterDiscriminator<DELETER>::Type Deleter; // 'Deleter' is an alias for the type of deleter used to destroy the // shared object. // DATA Deleter d_deleter; // deleter for this out-of-place instance TYPE *d_ptr_p; // pointer to out-of-place instance (held, not owned) Allocator *d_allocator_p; // memory allocator (held, not owned) private: // NOT IMPLEMENTED SharedPtrOutofplaceRep(const SharedPtrOutofplaceRep&); SharedPtrOutofplaceRep& operator=(const SharedPtrOutofplaceRep&); // PRIVATE CREATORS SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_ALLOCATOR_PTR>); SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FACTORY_PTR>); SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC>); SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC_ARG_T>); SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITHOUT_ALLOC>); // Create a 'SharedPtrOutofplaceRep' that manages the lifetime of the // specified 'ptr', using the specified 'deleter' to destroy 'ptr', and // using the specified 'basicAllocator' to supply memory. Note that // 'basicAllocator' will be used to destroy this representation object, // but not necessarily to destroy 'ptr'. Also note that // 'SharedPtrOutofplaceRep' should be created using // 'makeOutofplaceRep', which will call the appropriate private // constructor depending on the parameterized 'DELETER' type. ~SharedPtrOutofplaceRep(); // Destroy this representation object and if the shared object has not // been deleted, delete the shared object using the associated deleter. // Note that this destructor is never called explicitly. Instead, // 'disposeObject' destroys the shared object object and 'disposeRep' // deallocates this representation object. public: // CLASS METHODS static SharedPtrOutofplaceRep<TYPE, DELETER> *makeOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator = 0); // Return the address of a newly created 'SharedPtrOutofplaceRep' // object that manages the lifetime of the specified 'ptr', using the // specified 'deleter' to destroy 'ptr'. Optionally, specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. Note that the // parameterized 'DELETER' type will be used to deallocate the memory // pointed to by 'ptr'. // MANIPULATORS virtual void disposeObject(); // Destroy the object being referred to by this representation. This // method is automatically invoked by 'releaseRef' when the number of // shared references reaches zero and should not be explicitly invoked // otherwise. virtual void disposeRep(); // Destroy this representation object and deallocate the associated // memory. This method is automatically invoked by 'releaseRef' and // 'releaseWeakRef' when the number of weak references and the number // of shared references both reach zero and should not be explicitly // invoked otherwise. The behavior is undefined unless 'disposeObject' // has already been called for this representation. Note that this // 'disposeRep' method effectively serves as the representation // object's destructor. virtual void *getDeleter(const std::type_info& type); // Return a pointer to the deleter stored by the derived representation // (if any) if the deleter has the same type as that described by the // specified 'type', and a null pointer otherwise. // ACCESSORS virtual void *originalPtr() const; // Return the (untyped) address of the modifiable shared object to // which this object refers. TYPE *ptr() const; // Return the address of the modifiable shared object to which this // object refers. }; // ================================================= // class SharedPtrOutofplaceRep_DeleterDiscriminator // ================================================= template <class DELETER, bool IS_ALLOC_PTR> class SharedPtrOutofplaceRep_DeleterDiscriminator_Imp { // This 'class' provides the implementation of the // 'SharedPtrOutofplaceRep_DeleterDiscriminator' for the 'DELETER' template // parameter type, which is not 'Allocator *'. // PRIVATE TYPES enum { // Enumeration that calls meta-functions to describe properties of the // deleter. BSLMA_USES_ALLOC = UsesBslmaAllocator<DELETER>::value, BSLMA_USES_ALLOC_ARG_T = bslmf::UsesAllocatorArgT<DELETER>::value, BSLMA_IS_OBJ_PTR = bsl::is_pointer<DELETER>::value && !bslmf::IsFunctionPointer<DELETER>::value }; typedef SharedPtrOutofplaceRep_DeleterType DeleterType; // 'DeleterType' is an alias for the 'struct' that defines the types of // deleter used to destroy the shared object. public: // TYPES enum { // This enumeration contains the return value of the meta-function. VALUE = BSLMA_USES_ALLOC ? BSLMA_USES_ALLOC_ARG_T ? DeleterType::BSLMA_FUNCTOR_WITH_ALLOC_ARG_T : DeleterType::BSLMA_FUNCTOR_WITH_ALLOC : !BSLMA_IS_OBJ_PTR ? DeleterType::BSLMA_FUNCTOR_WITHOUT_ALLOC : DeleterType::BSLMA_FACTORY_PTR }; typedef typename bsl::conditional<bsl::is_function<DELETER>::value, DELETER *, DELETER>::type Type; // 'Type' represents the type of the deleter used to destroy the shared // object. }; template <class DELETER> class SharedPtrOutofplaceRep_DeleterDiscriminator_Imp<DELETER, true> { // This 'class' provides the implementation of the // 'SharedPtrOutofplaceRep_DeleterDiscriminator' for the 'DELETER' template // parameter type, which is 'Allocator *'. // PRIVATE TYPES typedef SharedPtrOutofplaceRep_DeleterType DeleterType; // 'DeleterType' is an alias for the 'struct' that defines the types of // deleter used to destroy the shared object. public: // TYPES enum { // This enumeration contains the return value of the meta-function. VALUE = DeleterType::BSLMA_ALLOCATOR_PTR }; typedef Allocator *Type; // 'Type' represents the type of the deleter used to destroy the shared // object. }; template <class DELETER> class SharedPtrOutofplaceRep_DeleterDiscriminator { // This 'class' provides two meta-functions for determining the enumerated // type and the C++ type of a deleter based on whether it is a pointer to a // function, a pointer to a factory deleter, or an instance of a // function-like deleter. // PRIVATE TYPES typedef SharedPtrOutofplaceRep_DeleterDiscriminator_Imp< DELETER, bsl::is_convertible<DELETER, Allocator *>::value> ImpType; public: // TYPES enum { // This enumeration contains the return value of the meta-function. VALUE = ImpType::VALUE }; typedef typename ImpType::Type Type; // 'Type' represents the type of the deleter used to destroy the shared // object. }; // =========================================== // struct SharedPtrOutofplaceRep_DeleterHelper // =========================================== struct SharedPtrOutofplaceRep_DeleterHelper { // This 'struct' provides utility functions to apply a deleter to a shared // object referred to by 'SharedPtrOutofplaceRep'. // PUBLIC TYPES typedef SharedPtrOutofplaceRep_DeleterType DeleterType; // 'DeleterType' is an alias for the 'struct' that defines the types of // deleter used to destroy the shared object. private: // PRIVATE CLASS METHODS template <class TYPE, class DELETER> static void deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_ALLOCATOR_PTR>); // Delete the specified 'ptr' using the specified 'deleter' that // implements the 'Allocator' protocol, which provides a 'deleteObject' // function that can be invoked to delete 'ptr'. template <class TYPE, class DELETER> static void deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FACTORY_PTR>); // Delete the specified 'ptr' using the specified 'deleter' that // provides a 'deleteObject' function that can be invoked to delete // 'ptr'. template <class TYPE, class DELETER> static void deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC>); // Delete the specified 'ptr' using the specified 'deleter' that is a // functor that takes an allocator at construction and can be invoked // to delete 'ptr'. template <class TYPE, class DELETER> static void deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC_ARG_T>); // Delete the specified 'ptr' using the specified 'deleter' that is a // functor that takes an allocator at construction using the // 'bsl::allocator_arg' idiom and can be invoked to delete 'ptr'. template <class TYPE, class DELETER> static void deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITHOUT_ALLOC>); // Delete the specified 'ptr' using the specified 'deleter' that is a // functor that does not take an allocator at construction and can be // invoked to delete 'ptr'. public: // CLASS METHODS template <class TYPE, class DELETER> static void deleteObject(TYPE *ptr, DELETER& deleter); // Delete the specified 'ptr' using the specified 'deleter'. }; // ========================================= // struct SharedPtrOutofplaceRep_InitProctor // ========================================= template <class TYPE, class DELETER> struct SharedPtrOutofplaceRep_InitProctor { // This proctor is used for out-of-place shared pointer instantiations. // Generally, a proctor is created prior to constructing a // 'SharedPtrOutofplaceRep' and released after successful construction. In // the event that an exception is thrown during construction of the // representation, the proctor will delete the provided pointer using the // provided deleter. Note that the provided deleter is held by reference // and must remain valid for the lifetime of the proctor. If the proctor // is not released before it's destruction, a copy of the deleter is // instantiated to delete the pointer (in case 'operator()' is // non-'const'). Also note that if the deleter throws during copy // construction, the provided pointer will not be destroyed. // DATA TYPE *d_ptr_p; // address of the managed object (held, not // owned) const DELETER& d_deleter; // deleter used to destroy managed object public: // CREATORS SharedPtrOutofplaceRep_InitProctor(TYPE *ptr, const DELETER& deleter); // Create a proctor referring to the specified 'ptr' and using the // specified 'deleter' to destroy 'ptr' when the proctor is destroyed. ~SharedPtrOutofplaceRep_InitProctor(); // Destroy this proctor and the object (if any) referred to by this // proctor. // MANIPULATORS void release(); // Release from management the object referred to by this proctor. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ---------------------------- // class SharedPtrOutofplaceRep // ---------------------------- // CLASS FUNCTIONS template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER> * SharedPtrOutofplaceRep<TYPE, DELETER>::makeOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator) { SharedPtrOutofplaceRep_InitProctor<TYPE, DELETER> proctor(ptr, deleter); enum { BSLMA_DELETER_TYPE = SharedPtrOutofplaceRep_DeleterDiscriminator<DELETER>::VALUE }; SharedPtrOutofplaceRep<TYPE, DELETER> *rep = 0; basicAllocator = Default::allocator(basicAllocator); rep = new (*basicAllocator) SharedPtrOutofplaceRep( ptr, deleter, basicAllocator, bsl::integral_constant<int, BSLMA_DELETER_TYPE>()); proctor.release(); return rep; } // CREATORS template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_ALLOCATOR_PTR>) : d_deleter(Default::allocator(deleter)) , d_ptr_p(ptr) , d_allocator_p(basicAllocator) { } template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FACTORY_PTR>) : d_deleter(deleter) , d_ptr_p(ptr) , d_allocator_p(basicAllocator) { } template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC>) : d_deleter(deleter, basicAllocator) , d_ptr_p(ptr) , d_allocator_p(basicAllocator) { } template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC_ARG_T>) : d_deleter(bsl::allocator_arg, basicAllocator, deleter) , d_ptr_p(ptr) , d_allocator_p(basicAllocator) { } template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::SharedPtrOutofplaceRep( TYPE *ptr, const DELETER& deleter, Allocator *basicAllocator, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITHOUT_ALLOC>) : d_deleter(deleter) , d_ptr_p(ptr) , d_allocator_p(basicAllocator) { } template <class TYPE, class DELETER> SharedPtrOutofplaceRep<TYPE, DELETER>::~SharedPtrOutofplaceRep() { } // MANIPULATORS template <class TYPE, class DELETER> void SharedPtrOutofplaceRep<TYPE, DELETER>::disposeObject() { SharedPtrOutofplaceRep_DeleterHelper::deleteObject(d_ptr_p, d_deleter); d_ptr_p = 0; } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep<TYPE, DELETER>::disposeRep() { // If 'd_allocator_p->deleteObject' is used to destroy the // 'SharedPtrOutofplaceRep' object, a virtual function call will be used // and a 'dynamic_cast' is required to obtain the address of the most // derived object to deallocate it. Knowing 'SharedPtrOutofplaceRep' is // the most derived class, this unnecessary overhead of a virtual function // call can be avoided by explicitly calling the destructor. This behavior // is guaranteed by the standard ([class.virtual] 13: "Explicit // qualification with the scope operator (5.1) suppresses the virtual call // mechanism.", page 224 of Working Draft 2007-10). Allocator *alloc = d_allocator_p; this->SharedPtrOutofplaceRep<TYPE, DELETER>::~SharedPtrOutofplaceRep(); alloc->deallocate(this); } template <class TYPE, class DELETER> inline void * SharedPtrOutofplaceRep<TYPE, DELETER>::getDeleter(const std::type_info& type) { return (typeid(d_deleter) == type) ? bsls::Util::addressOf(d_deleter) : 0; } // ACCESSORS template <class TYPE, class DELETER> inline void *SharedPtrOutofplaceRep<TYPE, DELETER>::originalPtr() const { return const_cast<void *>(static_cast<const void *>(d_ptr_p)); } template <class TYPE, class DELETER> inline TYPE *SharedPtrOutofplaceRep<TYPE, DELETER>::ptr() const { return d_ptr_p; } // ------------------------------------------- // struct SharedPtrOutofplaceRep_DeleterHelper // ------------------------------------------- // CLASS METHODS template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_ALLOCATOR_PTR>) { deleter->deleteObject(ptr); } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FACTORY_PTR>) { deleter->deleteObject(ptr); } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC>) { deleter(ptr); } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITH_ALLOC_ARG_T>) { deleter(ptr); } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject( TYPE *ptr, DELETER& deleter, bsl::integral_constant<int, DeleterType::BSLMA_FUNCTOR_WITHOUT_ALLOC>) { deleter(ptr); } template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_DeleterHelper::deleteObject(TYPE *ptr, DELETER& deleter) { enum { BSLMA_DELETER_TYPE = SharedPtrOutofplaceRep_DeleterDiscriminator<DELETER>::VALUE }; SharedPtrOutofplaceRep_DeleterHelper::deleteObject( ptr, deleter, bsl::integral_constant<int, BSLMA_DELETER_TYPE>()); } // --------------------------------------- // struct SharedPtrOutofplaceRep_InitProctor // --------------------------------------- // CREATORS template <class TYPE, class DELETER> inline SharedPtrOutofplaceRep_InitProctor<TYPE, DELETER>:: SharedPtrOutofplaceRep_InitProctor(TYPE *ptr, const DELETER& deleter) : d_ptr_p(ptr) , d_deleter(deleter) { } template <class TYPE, class DELETER> inline SharedPtrOutofplaceRep_InitProctor<TYPE, DELETER>:: ~SharedPtrOutofplaceRep_InitProctor() { // The definition of this function is intentionally *not* written as: //.. // if (d_ptr_p) { // DELETER tempDeleter(d_deleter); // SharedPtrOutofplaceRep_DeleterHelper::deleteObject(d_ptr_p, // tempDeleter); // } //.. // to work around a CC (Studio 12v4 on Solaris) compilation failure when // optimizations are enabled ('opt_exc_mt' and 'opt_exc_mt_64'). if (!d_ptr_p) { return; // RETURN } typename bsl::conditional<bsl::is_function<DELETER>::value, DELETER *, DELETER>::type tempDeleter(d_deleter); SharedPtrOutofplaceRep_DeleterHelper::deleteObject(d_ptr_p, tempDeleter); } // MANIPULATORS template <class TYPE, class DELETER> inline void SharedPtrOutofplaceRep_InitProctor<TYPE, DELETER>::release() { d_ptr_p = 0; } // ============================================================================ // TYPE TRAITS // ============================================================================ template <class TYPE, class DELETER> struct UsesBslmaAllocator<SharedPtrOutofplaceRep_InitProctor<TYPE, DELETER> > : bsl::false_type { }; } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------