// bslstl_sharedptrallocateinplacerep.h -*-C++-*- #ifndef INCLUDED_BSLSTL_SHAREDPTRALLOCATEINPLACEREP #define INCLUDED_BSLSTL_SHAREDPTRALLOCATEINPLACEREP #include <bsls_ident.h> BSLS_IDENT("$Id$ $CSID$") //@PURPOSE: Provide an in-place implementation of 'bslma::SharedPtrRep'. // //@CLASSES: // bslstl::SharedPtrAllocateInplaceRep: in-place 'shared_ptr' implementation // //@SEE_ALSO: bslma_sharedptrrep, bslma_sharedptrinplacerep, bslstl_sharedptr // //@DESCRIPTION: This component provides a class template, // 'bslstl::SharedPtrAllocateInplaceRep', proving a concrete implementation of // 'bslma::SharedPtrRep' for managing objects of the parameterized 'TYPE' that // are stored in-place in the representation, and are allocated by an allocator // that satisfies the requirements of an Allocator type in the C++11 standard. // Thus, only one memory allocation is required to create both the // representation and the managed object. When all references to the in-place // object are released (using 'releaseRef'), the destructor of 'TYPE' is // invoked. // ///Thread Safety ///------------- // 'bslstl::SharedPtrAllocateInplaceRep' 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 contained in // 'bslstl::SharedPtrAllocateInplaceRep'. #include <bslscm_version.h> #include <bslma_allocatortraits.h> #include <bslma_sharedptrrep.h> #include <bslma_usesbslmaallocator.h> #include <bsls_assert.h> #include <bsls_objectbuffer.h> #include <new> #include <typeinfo> namespace BloombergLP { namespace bslstl { // ================================= // class SharedPtrAllocateInplaceRep // ================================= template <class TYPE, class ALLOCATOR> class SharedPtrAllocateInplaceRep : public BloombergLP::bslma::SharedPtrRep { // This class provides a concrete implementation of the 'SharedPtrRep' // protocol for in-place instances of the (template parameter) 'TYPE'. // Upon destruction of this object, the destructor of 'TYPE' is invoked on // the shared object. // PRIVATE TYPES typedef typename bsl::allocator_traits<ALLOCATOR>:: template rebind_traits<SharedPtrAllocateInplaceRep> ReboundTraits; public: // PUBLIC TYPES typedef typename ReboundTraits::allocator_type ReboundAllocator; private: // DATA ReboundAllocator d_allocator; // copy of this object's allocator bsls::ObjectBuffer<TYPE> d_instance; // beginning of the in-place buffer // Note that 'd_instance' must be last in this layout to allow for the // possibility of creating an in-place uninitialized buffer, where it is // possible to access memory beyond the 'd_instance' footprint (refer to // 'bsl::shared_ptr::createInplaceUninitializedBuffer' for sample usage). private: // NOT IMPLEMENTED SharedPtrAllocateInplaceRep(const SharedPtrAllocateInplaceRep&); SharedPtrAllocateInplaceRep& operator=(const SharedPtrAllocateInplaceRep&); // PRIVATE CREATORS explicit SharedPtrAllocateInplaceRep( const ReboundAllocator& basicAllocator); // Create a 'SharedPtrAllocateInplaceRep' object having uninitialized // storage for an in-place instance of the parameterized 'TYPE'. Use // the specified 'basicAllocator' to supply memory and, upon a call to // 'disposeObject', to destroy the inplace object, and upon a call to // 'disposeRep' to destroy the copy the allocator and reclaim storage // for this object, ~SharedPtrAllocateInplaceRep(); // = delete // The destructor for this object should never be called. The in-place // 'TYPE' object will be destroyed by a call to 'destroyObject' and the // stored allocator for this object will be destroyed by a call to // 'destroyRep', which will then reclaim the storage occupied by this // object. public: // CLASS METHODS static SharedPtrAllocateInplaceRep *makeRep( ReboundAllocator basicAllocator); // Create a 'SharedPtrAllocateInplaceRep' object having storage for an // in-place uninitialized object of (template parameter) 'TYPE', and // return its address. Use the specified 'basicAllocator' to supply // memory and, upon a call to 'disposeRep', to destroy this // representation (and the in-place shared object). Note that the // function members 'ptr' and 'originalPtr' will return the address of // an uninitialized object. This object should be explicitly // initialized by the caller, and it is undefined behavior to call // 'disposeRep' until this object has been successfully constructed. // 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 // method effectively serves as the representation object's destructor. void *getDeleter(const std::type_info& type); // Ignore the specified 'type' and return a null pointer. Note that // there is no facility for the user to supply a deleter for an // in-place representation for a shared pointer. TYPE *ptr(); // Return the address of the modifiable shared object to which this // object refers. Note that in order to return a pointer to a // modifiable object, this function cannot be 'const' qualified as the // referenced object is stored internally as a data member. // ACCESSORS virtual void *originalPtr() const; // Return the (untyped) address of the modifiable shared object to // which this object refers. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // --------------------------------- // class SharedPtrAllocateInplaceRep // --------------------------------- // PRIVATE CREATORS template <class TYPE, class ALLOCATOR> inline SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::SharedPtrAllocateInplaceRep( const ReboundAllocator& basicAllocator) : d_allocator(basicAllocator) // 'd_instance' is intentionally left uninitialized. { } template <class TYPE, class ALLOCATOR> SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>:: ~SharedPtrAllocateInplaceRep() { BSLS_ASSERT_OPT(0); } // CLASS METHODS template <class TYPE, class ALLOCATOR> inline SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR> * SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::makeRep( ReboundAllocator basicAllocator) { SharedPtrAllocateInplaceRep *rep_p = ReboundTraits::allocate(basicAllocator, 1); new(rep_p) SharedPtrAllocateInplaceRep(basicAllocator); return rep_p; } // MANIPULATORS template <class TYPE, class ALLOCATOR> inline void SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::disposeObject() { ReboundTraits::destroy(d_allocator, ptr()); } template <class TYPE, class ALLOCATOR> inline void SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::disposeRep() { ReboundAllocator alloc(d_allocator); this->d_allocator.~ReboundAllocator(); ReboundTraits::deallocate(alloc, this, 1); } template <class TYPE, class ALLOCATOR> inline void * SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::getDeleter(const std::type_info&) { return 0; } template <class TYPE, class ALLOCATOR> inline TYPE *SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::ptr() { return d_instance.address(); } // ACCESSORS template <class TYPE, class ALLOCATOR> inline void * SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR>::originalPtr() const { return const_cast<void *>(static_cast<const void *>( const_cast<const TYPE *>(d_instance.address()))); } } // close package namespace // ============================================================================ // TYPE TRAITS // ============================================================================ namespace bslma { template <class TYPE, class ALLOCATOR> struct UsesBslmaAllocator< bslstl::SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR> > : bsl::false_type {}; } // close namespace bslma } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2014 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 ----------------------------------