// bslma_deleterhelper.h -*-C++-*- #ifndef INCLUDED_BSLMA_DELETERHELPER #define INCLUDED_BSLMA_DELETERHELPER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide namespace for functions used to delete objects. // //@CLASSES: // bslma::DeleterHelper: non-primitive functions for deleting objects // //@SEE_ALSO: bslma_rawdeleterguard, bslmf_ispolymporphic // //@DESCRIPTION: This component provides non-primitive procedures used to delete // objects of parameterized 'TYPE' by first calling the destructor of the // object, and then freeing the memory footprint of the object using a // parameterized 'ALLOCATOR' (allocator or pool) provided as a second argument. // The "raw" method ('deleteObjectRaw') should be used only if we are sure that // the supplied object is !not! of a type that is a secondary base class -- // i.e., the object's address is (numerically) the same as when it was // originally dispensed by 'ALLOCATOR'. The non-"raw" 'deleteObject' has no // such restriction. Note that this component will fail to compile when // instantiated for a class that gives a false-positive for the type trait // 'bsl::is_polymorphic'. See the 'bslmf_ispolymporphic' component for more // details. // ///Usage ///----- // The following 'my_RawDeleterGuard' class defines a guard that // unconditionally deletes a managed object upon destruction. Via the // 'deleteObjectRaw' method supplied by this component, the guard's destructor // first destroys the managed object, then deallocates the footprint of the // object. The declaration of 'my_RawDeleterGuard' follows: //.. // template <class TYPE, class ALLOCATOR> // class my_RawDeleterGuard { // // This class implements a guard that unconditionally deletes a managed // // object upon destruction by first invoking the object's destructor, // // and then invoking the 'deallocate' method of an allocator (or pool) // // of parameterized 'ALLOCATOR' type supplied at construction. // // // DATA // TYPE *d_object_p; // managed object // ALLOCATOR *d_allocator_p; // allocator or pool (held, not owned) // // // NOT IMPLEMENTED // my_RawDeleterGuard(const my_RawDeleterGuard&); // my_RawDeleterGuard& operator=(const my_RawDeleterGuard&); // // public: // // CREATORS // my_RawDeleterGuard(TYPE *object, ALLOCATOR *allocator); // // Create a raw deleter guard that unconditionally manages the // // specified 'object', and that uses the specified 'allocator' to // // delete 'object' upon the destruction of this guard. The // // behavior is undefined unless 'object' and 'allocator' are // // non-zero, and 'allocator' supplied the memory for 'object'. // // Note that 'allocator' must remain valid throughout the lifetime // // of this guard. // // ~my_RawDeleterGuard(); // // Destroy this raw deleter guard and delete the object it manages // // by first invoking the destructor of the (managed) object, and // // then invoking the 'deallocate' method of the allocator (or pool) // // that was supplied with the object at construction. // }; //.. // The 'deleteObjectRaw' method is used in the destructor as follows: //.. // template <class TYPE, class ALLOCATOR> // inline // my_RawDeleterGuard<TYPE, ALLOCATOR>::~my_RawDeleterGuard() // { // bslma::DeleterHelper::deleteObjectRaw(d_object_p, d_allocator_p); // } //.. // Note that we have denoted our guard to be a "raw" guard in keeping with this // use of 'deleteObjectRaw' (as opposed to 'deleteObject'). #include <bslscm_version.h> #include <bslmf_ispolymorphic.h> #include <bsls_assert.h> #include <bsls_platform.h> namespace BloombergLP { namespace bslma { // ==================== // struct DeleterHelper // ==================== struct DeleterHelper { // This struct provides a namespace for helper functions used for deleting // objects in various pools and allocators. // CLASS METHODS template <class TYPE, class ALLOCATOR> static void deleteObject(const TYPE *object, ALLOCATOR *allocator); // Destroy the specified 'object' based on its dynamic type and then // use the specified 'allocator' to deallocate its memory footprint. // Do nothing if 'object' is a null pointer. The behavior is undefined // unless 'allocator' is non-null, and 'object', when cast // appropriately to 'void *', was allocated using 'allocator' and has // not already been deallocated. Note that // 'dynamic_cast<void *>(object)' is applied if 'TYPE' is polymorphic, // and 'static_cast<void *>(object)' is applied otherwise. template <class TYPE, class ALLOCATOR> static void deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator); // Destroy the specified 'object' and then use the specified // 'allocator' to deallocate its memory footprint. Do nothing if // 'object' is a null pointer. The behavior is undefined unless // 'allocator' is non-null, 'object' is !not! a secondary base class // pointer (i.e., the address is (numerically) the same as when it was // originally dispensed by 'allocator'), and 'object' was allocated // using 'allocator' and has not already been deallocated. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ================================= // local struct DeleterHelper_Helper // ================================= template <bool IS_POLYMORPHIC> struct DeleterHelper_Helper { template <class TYPE> static void *caster(const TYPE *object) { return static_cast<void *>(const_cast<TYPE *>(object)); } }; template <> struct DeleterHelper_Helper<true> { template <class TYPE> static void *caster(const TYPE *object) { return dynamic_cast<void *>(const_cast<TYPE *>(object)); } }; // -------------------- // struct DeleterHelper // -------------------- // CLASS METHODS template <class TYPE, class ALLOCATOR> inline void DeleterHelper::deleteObject(const TYPE *object, ALLOCATOR *allocator) { BSLS_ASSERT_SAFE(allocator); if (0 != object) { void *address = DeleterHelper_Helper< bsl::is_polymorphic<TYPE>::value>::caster(object); BSLS_ASSERT_OPT(address); #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130 const_cast<TYPE *>(object)->~TYPE(); #else object->~TYPE(); #endif allocator->deallocate(address); } } template <class TYPE, class ALLOCATOR> inline void DeleterHelper::deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator) { BSLS_ASSERT_SAFE(allocator); if (0 != object) { void *address = const_cast<TYPE *>(object); #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130 const_cast<TYPE *>(object)->~TYPE(); #else object->~TYPE(); #endif allocator->deallocate(address); } } } // close package namespace #ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY // ============================================================================ // BACKWARD COMPATIBILITY // ============================================================================ typedef bslma::DeleterHelper bslma_DeleterHelper; // This alias is defined for backward compatibility. #endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY } // 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 ----------------------------------