//============================================================================ // Contents: // // Declaration of allocation functions that confer reference counting // capabilities on the memory allocated for objects of any type. Global // functions are provided that make any object so allocated satisfy the // countability requirements defined for any parameter of countable_ptr. // // The code demonstrates how reference counting can be attached at allocation // time to objects of any type. In conjunction with countable_ptr, it // shows how the Attached Counted Handle/Body idiom can be implemented // non-intrusively for any type; a discrete status normally reserved for // the Detached Counted Handle/Body idiom. // // History: // // Initial version created by Kevlin Henney, kevlin@acm.org, January 1998. // // Permissions: // // Copyright Kevlin Henney, 1998. All rights reserved. // // Permission to use, copy, modify, and distribute this software for any // purpose is hereby granted without fee, provided that this copyright and // permissions notice appear in all copies and derivatives, and that no // charge may be made for the software and its documentation except to cover // cost of distribution. // // This software is provided "as is" without express or implied warranty. // // Notes: // // Although the countable requirements specified in "countable_ptr.hpp" are // satisfied by objects allocated by new(countable), there is no source // dependency on that header; objects allocated by new(countable) may be // used, if so desired, independently of countable_ptr. // // For practical reasons the global, rather than a named namespace, has been // used to hold the contents of this header. In future the use of a separate // namespace is preferred and recommended for the appropriate declarations // (ie not the allocator operators). // // This code has been written to conform to standard C++ (in final draft // status at the time of writing); any deviations are noted. It has been // compiled successfully using the operational subset of standard features // implemented by Microsoft Visual C++ 5.0. //============================================================================ #ifndef COUNTABLE_NEW_INCLUDED #define COUNTABLE_NEW_INCLUDED #include // for std::bad_alloc #include // for size_t //---------------------------------------------------------------------------- // Description: // // Declaration of allocation functions, type and object that allow objects of // any type to be allocated and satisfy countable requirements. // // Requirements: // // The type of the object allocated should not otherwise already satisfy // countable requirements. // // Objects allocated by new(countable) shall not be passed to delete; the // only form of memory management supported for objects allocated by // new(countable) is that defined for countable objects. // // Notes: // // The countable_new is a dummy type with only one instance, countable. These // are required for overloading operator new so that the form yielding // countable memory is distinguished from the normal global new, ie to // allocate a countable object new(countable) is used rather than new. // // For brevity the overloaded operator new for nothrow has been omitted, but // it is trivial to provide. //---------------------------------------------------------------------------- struct countable_new; extern const countable_new countable; void *operator new(size_t, const countable_new &) throw(std::bad_alloc); void operator_delete(void *, const countable_new &) throw(); //---------------------------------------------------------------------------- // Description: // // Declaration of global functions that allow objects allocated by // new(countable) to satisfy countable requirements. // // Requirements: // // Objects manipulated by these functions must have been allocated by // new(countable). // // Notes: // // Countability is not seen as a concrete property of objects allocated by // new(countable), and therefore countability is not part of an object's // logical state. This means that all the countable operations on an object // may be performed on a const object. // // The dispose function supports a default argument to make any use of // countable objects independent of countable_ptr marginally easier. // // As there is no requirement that a countable type must be a class, typename // is used to introduce the type parameter for dispose rather than class. If // your compiler does not yet support this use of typename, you can replace // it with class. // // If your compiler supports older style template functions that require an // exact match on the type of non-templated arguments, the dispose function // will cause problems and your code will not compile. This problem can be // worked around in part by making the type of the second argument the same // as the first. However, this means that as dispose cannot be overloaded // successfully, only one countable strategy can be used per translation // unit. //---------------------------------------------------------------------------- void acquire(const void *); void release(const void *); size_t acquired(const void *); template void dispose(const countable_type *, const void * = 0); //---------------------------------------------------------------------------- // Description: // // Definition of dispose template function. // // Notes: // // This definition could be placed in a separate header file or, for systems // that support separate compilation of templates, in a source file. // // The function is a likely candidate for explicit inlining, but for the // purposes of demonstration such an optimisation has not been deemed // necessary. //---------------------------------------------------------------------------- template void dispose(const countable_type *ptr, const void *) { ptr->~countable_type(); operator_delete(const_cast(ptr), countable); } #endif