From 6616cd86ef3fcd66c6c8fc734a8b741e27cba89c Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 17 Aug 2013 19:39:53 -0700 Subject: [PATCH] Add ContainerDeletePolicy for ownership containers --- .../Builds/VisualStudio2012/beast.vcxproj | 4 +- .../VisualStudio2012/beast.vcxproj.filters | 15 ++- .../events/beast_OncePerSecond.cpp | 2 +- .../memory/beast_GlobalFifoFreeStore.h | 2 +- .../memory/beast_GlobalPagedFreeStore.h | 2 +- .../beast/modules/beast_core/beast_core.h | 1 + .../beast_core/containers/beast_OwnedArray.h | 18 ++-- .../memory/beast_ContainerDeletePolicy.h | 48 +++++++++ .../beast_core/memory/beast_ScopedPointer.h | 12 ++- .../beast_core/memory/beast_SharedObject.h | 99 ++++++++++++------- .../beast_core/memory/beast_SharedSingleton.h | 7 +- .../modules/beast_sqdb/source/session.cpp | 2 +- 12 files changed, 144 insertions(+), 68 deletions(-) create mode 100644 Subtrees/beast/modules/beast_core/memory/beast_ContainerDeletePolicy.h diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj index 9017ba1d73..accc61fdc9 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj @@ -70,11 +70,8 @@ - - - @@ -183,6 +180,7 @@ + diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters index b57b3da3de..73c1c0a735 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters @@ -815,15 +815,6 @@ beast_asio\basics - - beast_asio\basics - - - beast_asio\basics - - - beast_asio\basics - beast_asio\basics @@ -857,6 +848,12 @@ beast_asio\handshake + + beast_asio\basics + + + beast_core\memory + diff --git a/Subtrees/beast/modules/beast_basics/events/beast_OncePerSecond.cpp b/Subtrees/beast/modules/beast_basics/events/beast_OncePerSecond.cpp index 6b436ec51c..0fed5ec806 100644 --- a/Subtrees/beast/modules/beast_basics/events/beast_OncePerSecond.cpp +++ b/Subtrees/beast/modules/beast_basics/events/beast_OncePerSecond.cpp @@ -21,7 +21,7 @@ class OncePerSecond::TimerSingleton : public SharedSingleton , private InterruptibleThread::EntryPoint { -private: +public: TimerSingleton () : SharedSingleton ( SingletonLifetime::persistAfterCreation) diff --git a/Subtrees/beast/modules/beast_basics/memory/beast_GlobalFifoFreeStore.h b/Subtrees/beast/modules/beast_basics/memory/beast_GlobalFifoFreeStore.h index 987a584cde..bdeff7ce6f 100644 --- a/Subtrees/beast/modules/beast_basics/memory/beast_GlobalFifoFreeStore.h +++ b/Subtrees/beast/modules/beast_basics/memory/beast_GlobalFifoFreeStore.h @@ -45,7 +45,7 @@ public: return new GlobalFifoFreeStore; } -private: +public: GlobalFifoFreeStore () : SharedSingleton > (SingletonLifetime::persistAfterCreation) diff --git a/Subtrees/beast/modules/beast_basics/memory/beast_GlobalPagedFreeStore.h b/Subtrees/beast/modules/beast_basics/memory/beast_GlobalPagedFreeStore.h index 17c88af013..aa52d65066 100644 --- a/Subtrees/beast/modules/beast_basics/memory/beast_GlobalPagedFreeStore.h +++ b/Subtrees/beast/modules/beast_basics/memory/beast_GlobalPagedFreeStore.h @@ -30,7 +30,7 @@ class BEAST_API GlobalPagedFreeStore : public SharedSingleton , LeakChecked { -private: +public: GlobalPagedFreeStore (); ~GlobalPagedFreeStore (); diff --git a/Subtrees/beast/modules/beast_core/beast_core.h b/Subtrees/beast/modules/beast_core/beast_core.h index 683e845a8b..5cc6d85086 100644 --- a/Subtrees/beast/modules/beast_core/beast_core.h +++ b/Subtrees/beast/modules/beast_core/beast_core.h @@ -227,6 +227,7 @@ namespace beast #include "text/beast_CharPointer_UTF8.h" #include "text/beast_LexicalCast.h" +#include "memory/beast_ContainerDeletePolicy.h" #include "time/beast_PerformedAtExit.h" #include "diagnostic/beast_LeakChecked.h" #include "memory/beast_ByteOrder.h" diff --git a/Subtrees/beast/modules/beast_core/containers/beast_OwnedArray.h b/Subtrees/beast/modules/beast_core/containers/beast_OwnedArray.h index 684a253d8b..8004e6801a 100644 --- a/Subtrees/beast/modules/beast_core/containers/beast_OwnedArray.h +++ b/Subtrees/beast/modules/beast_core/containers/beast_OwnedArray.h @@ -409,9 +409,10 @@ public: } } - delete toDelete; // don't want to use a ScopedPointer here because if the - // object has a private destructor, both OwnedArray and - // ScopedPointer would need to be friend classes.. + // don't want to use a ScopedPointer here because if the + // object has a private destructor, both OwnedArray and + // ScopedPointer would need to be friend classes.. + ContainerDeletePolicy ::destroy (toDelete); } else { @@ -591,9 +592,10 @@ public: } } - delete toDelete; // don't want to use a ScopedPointer here because if the - // object has a private destructor, both OwnedArray and - // ScopedPointer would need to be friend classes.. + // don't want to use a ScopedPointer here because if the + // object has a private destructor, both OwnedArray and + // ScopedPointer would need to be friend classes.. + ContainerDeletePolicy ::destroy (toDelete); if ((numUsed << 1) < data.numAllocated) minimiseStorageOverheads(); @@ -682,7 +684,7 @@ public: { for (int i = startIndex; i < endIndex; ++i) { - delete data.elements [i]; + ContainerDeletePolicy ::destroy (data.elements [i]); data.elements [i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer) } } @@ -879,7 +881,7 @@ private: void deleteAllObjects() { while (numUsed > 0) - delete data.elements [--numUsed]; + ContainerDeletePolicy ::destroy (data.elements [--numUsed]); } }; diff --git a/Subtrees/beast/modules/beast_core/memory/beast_ContainerDeletePolicy.h b/Subtrees/beast/modules/beast_core/memory/beast_ContainerDeletePolicy.h new file mode 100644 index 0000000000..2a282b2940 --- /dev/null +++ b/Subtrees/beast/modules/beast_core/memory/beast_ContainerDeletePolicy.h @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CONTAINERDELETEPOLICY_H_INCLUDED +#define BEAST_CONTAINERDELETEPOLICY_H_INCLUDED + +/** The DeletePolicy provides a way to destroy objects stored in containers. + + This is a specialized class. The default implementation + calls operator delete. You can customize it for your classes + by providing a suitable specialization. + + A DeletePolicy must support these concepts: + DefaultConstructible + MoveConstructible (C++11) + CopyConstructible + MoveAssignable (C++11) + Destructible +*/ + +/** The DefaultDeletePolicy simply calls operator delete. +*/ +template +struct ContainerDeletePolicy +{ + static inline void destroy (T* t) + { + delete t; + } +}; + +#endif diff --git a/Subtrees/beast/modules/beast_core/memory/beast_ScopedPointer.h b/Subtrees/beast/modules/beast_core/memory/beast_ScopedPointer.h index 32d8aa8327..60d1a2952a 100644 --- a/Subtrees/beast/modules/beast_core/memory/beast_ScopedPointer.h +++ b/Subtrees/beast/modules/beast_core/memory/beast_ScopedPointer.h @@ -67,7 +67,8 @@ class ScopedPointer : public Uncopyable public: //============================================================================== /** Creates a ScopedPointer containing a null pointer. */ - inline ScopedPointer() noexcept : object (nullptr) + inline ScopedPointer() noexcept + : object (nullptr) { } @@ -92,7 +93,10 @@ public: /** Destructor. This will delete the object that this ScopedPointer currently refers to. */ - inline ~ScopedPointer() { delete object; } + inline ~ScopedPointer() + { + ContainerDeletePolicy ::destroy (object); + } /** Changes this ScopedPointer to point to a new object. @@ -114,7 +118,7 @@ public: ObjectType* const oldObject = object; object = objectToTransferFrom.object; objectToTransferFrom.object = nullptr; - delete oldObject; + ContainerDeletePolicy ::destroy (oldObject); } return *this; @@ -133,7 +137,7 @@ public: { ObjectType* const oldObject = object; object = newObjectToTakePossessionOf; - delete oldObject; + ContainerDeletePolicy ::destroy (oldObject); } return *this; diff --git a/Subtrees/beast/modules/beast_core/memory/beast_SharedObject.h b/Subtrees/beast/modules/beast_core/memory/beast_SharedObject.h index 87f3d4b255..7aec64ff81 100644 --- a/Subtrees/beast/modules/beast_core/memory/beast_SharedObject.h +++ b/Subtrees/beast/modules/beast_core/memory/beast_SharedObject.h @@ -21,12 +21,11 @@ */ //============================================================================== -#ifndef BEAST_REFERENCECOUNTEDOBJECT_BEASTHEADER -#define BEAST_REFERENCECOUNTEDOBJECT_BEASTHEADER +#ifndef BEAST_SHAREDOBJECT_H_INCLUDED +#define BEAST_SHAREDOBJECT_H_INCLUDED #include "beast_Atomic.h" - //============================================================================== /** Adds reference-counting to an object. @@ -75,14 +74,23 @@ public: /** Decreases the object's reference count. - If the count gets to zero, the object will be deleted. + If doDelete is true the object will be deleted when the reference + count drops to zero. The delete is performed using the regular + operator and does NOT go through the ContainerDeletePolicy. + + The return value indicates if the reference count dropped to zero, + so callers who know the derived type can use the ContainerDeletePolicy. */ - inline void decReferenceCount() noexcept + inline bool decReferenceCount (bool doDelete = true) noexcept { bassert (getReferenceCount() > 0); - if (--refCount == 0) - delete this; + { + if (doDelete) + delete this; + return true; + } + return false; } /** Returns the object's current reference count. */ @@ -115,7 +123,6 @@ private: Atomic refCount; }; - //============================================================================== /** Adds reference-counting to an object. @@ -143,16 +150,26 @@ public: /** Decreases the object's reference count. - If the count gets to zero, the object will be deleted. + If doDelete is true the object will be deleted when the reference + count drops to zero. The delete is performed using the regular + operator and does NOT go through the ContainerDeletePolicy. + + The return value indicates if the reference count dropped to zero, + so callers who know the derived type can use the ContainerDeletePolicy. */ - inline void decReferenceCount() noexcept + inline bool decReferenceCount (bool doDelete = true) noexcept { bassert (getReferenceCount() > 0); - if (--refCount == 0) - delete this; + { + if (doDelete) + delete this; + return true; + } + return false; } + /** Returns the object's current reference count. */ inline int getReferenceCount() const noexcept { return refCount; } @@ -190,12 +207,12 @@ private: @see SharedObject, SharedObjectArray */ -template +template class SharedObjectPtr { public: /** The class being referenced by this pointer. */ - typedef SharedObjectClass ReferencedType; + typedef Object ReferencedType; //============================================================================== /** Creates a pointer to a null object. */ @@ -208,7 +225,7 @@ public: This will increment the object's reference-count if it is non-null. */ - inline SharedObjectPtr (SharedObjectClass* const refCountedObject) noexcept + inline SharedObjectPtr (Object* const refCountedObject) noexcept : referencedObject (refCountedObject) { if (refCountedObject != nullptr) @@ -239,7 +256,7 @@ public: */ template inline SharedObjectPtr (const SharedObjectPtr& other) noexcept - : referencedObject (static_cast (other.get())) + : referencedObject (static_cast (other.get())) { if (referencedObject != nullptr) referencedObject->incReferenceCount(); @@ -263,7 +280,7 @@ public: template SharedObjectPtr& operator= (const SharedObjectPtr& other) { - return operator= (static_cast (other.get())); + return operator= (static_cast (other.get())); } #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS @@ -280,18 +297,21 @@ public: The reference count of the old object is decremented, and it might be deleted if it hits zero. The new object's count is incremented. */ - SharedObjectPtr& operator= (SharedObjectClass* const newObject) + SharedObjectPtr& operator= (Object* const newObject) { if (referencedObject != newObject) { if (newObject != nullptr) newObject->incReferenceCount(); - SharedObjectClass* const oldObject = referencedObject; + Object* const oldObject = referencedObject; referencedObject = newObject; if (oldObject != nullptr) - oldObject->decReferenceCount(); + { + if (oldObject->decReferenceCount (false)) + ContainerDeletePolicy ::destroy (oldObject); + } } return *this; @@ -305,19 +325,22 @@ public: inline ~SharedObjectPtr() { if (referencedObject != nullptr) - referencedObject->decReferenceCount(); + { + if (referencedObject->decReferenceCount (false)) + ContainerDeletePolicy ::destroy (referencedObject); + } } /** Returns the object that this pointer references. The pointer returned may be zero, of course. */ - inline operator SharedObjectClass*() const noexcept + inline operator Object*() const noexcept { return referencedObject; } // the -> operator is called on the referenced object - inline SharedObjectClass* operator->() const noexcept + inline Object* operator->() const noexcept { return referencedObject; } @@ -325,7 +348,7 @@ public: /** Returns the object that this pointer references. The pointer returned may be zero, of course. */ - inline SharedObjectClass* get() const noexcept + inline Object* get() const noexcept { return referencedObject; } @@ -333,55 +356,55 @@ public: /** Returns the object that this pointer references. The pointer returned may be zero, of course. */ - inline SharedObjectClass* getObject() const noexcept + inline Object* getObject() const noexcept { return referencedObject; } private: //============================================================================== - SharedObjectClass* referencedObject; + Object* referencedObject; }; /** Compares two SharedObjectPointers. */ -template -bool operator== (const SharedObjectPtr& object1, SharedObjectClass* const object2) noexcept +template +bool operator== (const SharedObjectPtr& object1, Object* const object2) noexcept { return object1.get() == object2; } /** Compares two SharedObjectPointers. */ -template -bool operator== (const SharedObjectPtr& object1, const SharedObjectPtr& object2) noexcept +template +bool operator== (const SharedObjectPtr& object1, const SharedObjectPtr& object2) noexcept { return object1.get() == object2.get(); } /** Compares two SharedObjectPointers. */ -template -bool operator== (SharedObjectClass* object1, SharedObjectPtr& object2) noexcept +template +bool operator== (Object* object1, SharedObjectPtr& object2) noexcept { return object1 == object2.get(); } /** Compares two SharedObjectPointers. */ -template -bool operator!= (const SharedObjectPtr& object1, const SharedObjectClass* object2) noexcept +template +bool operator!= (const SharedObjectPtr& object1, const Object* object2) noexcept { return object1.get() != object2; } /** Compares two SharedObjectPointers. */ -template -bool operator!= (const SharedObjectPtr& object1, SharedObjectPtr& object2) noexcept +template +bool operator!= (const SharedObjectPtr& object1, SharedObjectPtr& object2) noexcept { return object1.get() != object2.get(); } /** Compares two SharedObjectPointers. */ -template -bool operator!= (SharedObjectClass* object1, SharedObjectPtr& object2) noexcept +template +bool operator!= (Object* object1, SharedObjectPtr& object2) noexcept { return object1 != object2.get(); } diff --git a/Subtrees/beast/modules/beast_core/memory/beast_SharedSingleton.h b/Subtrees/beast/modules/beast_core/memory/beast_SharedSingleton.h index 87096cf836..fc6ab0c265 100644 --- a/Subtrees/beast/modules/beast_core/memory/beast_SharedSingleton.h +++ b/Subtrees/beast/modules/beast_core/memory/beast_SharedSingleton.h @@ -139,10 +139,13 @@ public: m_refs.addref (); } - inline void decReferenceCount () noexcept + inline bool decReferenceCount (bool = true) noexcept { if (m_refs.release ()) destroySingleton (); + + // We let destroySingleton enforce the ContainerDeletePolicy + return false; } // Caller must synchronize. @@ -183,7 +186,7 @@ private: { bassert (m_lifetime != neverDestroyed); - delete this; + ContainerDeletePolicy ::destroy (static_cast (this)); } } diff --git a/Subtrees/beast/modules/beast_sqdb/source/session.cpp b/Subtrees/beast/modules/beast_sqdb/source/session.cpp index de1778472f..f3a1ba8e18 100644 --- a/Subtrees/beast/modules/beast_sqdb/source/session.cpp +++ b/Subtrees/beast/modules/beast_sqdb/source/session.cpp @@ -62,7 +62,7 @@ namespace sqdb class session::Sqlite3 : public SharedSingleton { -private: +public: friend class SharedSingleton ; Sqlite3() : SharedSingleton (SingletonLifetime::persistAfterCreation)