// bslma_defaultallocatorguard.h -*-C++-*- #ifndef INCLUDED_BSLMA_DEFAULTALLOCATORGUARD #define INCLUDED_BSLMA_DEFAULTALLOCATORGUARD #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide scoped guard to temporarily change the default allocator. // //@CLASSES: // bslma::DefaultAllocatorGuard: default-allocator scoped guard // //@SEE_ALSO: bslma_allocator, bslma_default // //@DESCRIPTION: This component provides an object, // 'bslma::DefaultAllocatorGuard', that serves as a "scoped guard" to enable // the temporary replacement of the process-wide default allocator. This // functionality is intended for *testing* only, and in no event should this // component be used except in 'main'. // // The guard object takes as its constructor argument the address of an object // of a class derived from 'bslma::Allocator'. The default allocator at the // time of guard construction is held by the guard, and the // constructor-argument allocator is installed as the new process-wide default // allocator (via a call to 'bslma::Default::setDefaultAllocatorRaw'). Upon // destruction of the guard object, its held allocator is restored as the // process-wide default allocator (via another call to // 'bslma::Default::setDefaultAllocatorRaw'). // ///Usage ///----- // The 'bslma_default' component ensures that, unless the owner of 'main' or // some intervening code explicitly installs a default allocator, the // 'bslma::NewDeleteAllocator::singleton()' will be the default allocator for // that process (i.e., calls to 'bslma::Default::defaultAllocator()' will // return the new-delete allocator unless someone has set the default allocator // to a different allocator intentionally). Consider for purposes of this // illustrative example the case where we, as owners of a test driver 'main', // can count on the 'bslma::NewDeleteAllocator' singleton being the default. // // Consider now that, for testing purposes, we want a simple counting allocator // that uses 'new' and 'delete', and that also keeps count of the number of // memory blocks that have been allocated but never deallocated. (Note that, // in testing real production code, 'bslma::TestAllocator' serves this // purpose.) //.. // class my_CountingAllocator : public bslma::Allocator // { // int d_blocksOutstanding; // public: // my_CountingAllocator(); // ~my_CountingAllocator(); // // virtual void *allocate(int size); // virtual void deallocate(void *address); // // int blocksOutstanding() const { return d_blocksOutstanding; } // }; // // inline // my_CountingAllocator::my_CountingAllocator() // : d_blocksOutstanding(0) // { // } // // inline // my_CountingAllocator::~my_CountingAllocator() // { // if (0 < d_blocksOutstanding) { // std::cout << "***ERROR: Memory Leak***" << std::endl // << d_blocksOutstanding << " block(s) leaked. " // << "Program aborting." << std::endl; // assert(0); // } // } // // inline // void *my_CountingAllocator::allocate(int size) // { // ++d_blocksOutstanding; // return operator new(size); // } // // inline // void my_CountingAllocator::deallocate(void *address) // { // --d_blocksOutstanding; // operator delete(address); // } //.. // We may now write a test driver for some component that uses a // 'bslma::Allocator' and the 'bslma::Default' mechanism. First, we confirm // that the 'bslma::NewDeleteAllocator' singleton is indeed installed. //.. // //my_component.t.cpp // // // ... // // int main() // { // // ... // bslma::NewDeleteAllocator *na = // &bslma::NewDeleteAllocator::singleton(); // assert(na == bslma::Default::defaultAllocator()); //.. // Now, we can go into some inner scope and use a guard object to install a // test allocator as the default for any newly created objects. When the inner // scope ends, the guard will be destroyed, automatically restoring the // original default allocator. //.. // { // my_CountingAllocator testAllocator; // bslma::DefaultAllocatorGuard guard(&testAllocator); // assert(&testAllocator == bslma::Default::defaultAllocator()); // // // Create and test the object under test, which will use the // // test allocator *by* *default*. // // // ... // } // assert(na == bslma::Default::defaultAllocator()); //.. // If the test block above has a memory leak, the program will print an error // to 'stdout' and abort. Otherwise, the new-delete allocator will be // re-installed as the default allocator, and the program will proceed to the // next block of code. #include <bslscm_version.h> namespace BloombergLP { namespace bslma { class Allocator; // =========================== // class DefaultAllocatorGuard // =========================== class DefaultAllocatorGuard { // Upon construction, an object of this class saves the current default // allocator and installs the user-specified allocator as the default // allocator. On destruction, the original default allocator is restored. // Objects of this class are intended for testing purposes *only* and are // *not* guaranteed to be safe in production environments. Allocator *d_original_p; // original (to be restored at destruction) // NOT IMPLEMENTED DefaultAllocatorGuard(const DefaultAllocatorGuard&); DefaultAllocatorGuard& operator=(const DefaultAllocatorGuard&); public: // CREATORS explicit DefaultAllocatorGuard(Allocator *temporary); // Create a scoped guard that installs the specified 'temporary' // allocator as the default allocator. Note that the default allocator // is automatically restored to the original allocator on destruction. ~DefaultAllocatorGuard(); // Restore the default allocator that was in place when this scoped // guard was created and destroy this guard. }; } // close package namespace #ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY // ============================================================================ // BACKWARD COMPATIBILITY // ============================================================================ typedef bslma::DefaultAllocatorGuard bslma_DefaultAllocatorGuard; // 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 ----------------------------------