williamr@4: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). williamr@4: // All rights reserved. williamr@4: // This component and the accompanying materials are made available williamr@4: // under the terms of "Eclipse Public License v1.0" williamr@4: // which accompanies this distribution, and is available williamr@4: // at the URL "http://www.eclipse.org/legal/epl-v10.html". williamr@4: // williamr@4: // Initial Contributors: williamr@4: // Nokia Corporation - initial contribution. williamr@4: // williamr@4: // Contributors: williamr@4: // williamr@4: // Description: williamr@4: // williamr@4: williamr@4: #ifndef EMANAGED_H williamr@4: #define EMANAGED_H williamr@4: williamr@4: #include williamr@4: williamr@4: #include williamr@4: #include williamr@4: williamr@4: williamr@4: williamr@4: williamr@4: /** williamr@4: @file williamr@4: @brief Utility class templates that provide RAII-based automatic williamr@4: resource management. williamr@4: williamr@4: @publishedAll williamr@4: @released williamr@4: */ williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation function.In order to override the default cleanup williamr@4: strategy for a particular type, use the provided williamr@4: DEFINE_CLEANUP_FUNCTION utility macro williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: template williamr@4: inline void CallCleanupFunction(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->Close(); williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: Utility macro that can be used for defining the cleanup member williamr@4: function for a class (typically a R-class). williamr@4: williamr@4: This macro can be used in the same namespace in which the R-class is williamr@4: defined or in a namespace in which the R-class is used. williamr@4: williamr@4: Example: williamr@4: williamr@4: class RDestroyableClass williamr@4: { williamr@4: public: williamr@4: // ... williamr@4: void Destroy(); // member function used for cleanup and releasing the resources owned by a RDestroyableClass object williamr@4: // ... williamr@4: }; williamr@4: williamr@4: DEFINE_CLEANUP_FUNCTION(RDestroyableClass, Destroy) williamr@4: williamr@4: @param AClass the name of the class williamr@4: @param CleanupMemFun the name of the cleanup member function of the class williamr@4: */ williamr@4: #define DEFINE_CLEANUP_FUNCTION(AClass, CleanupMemFun) \ williamr@4: inline void CallCleanupFunction(AClass* aObjPtr) \ williamr@4: { \ williamr@4: aObjPtr->CleanupMemFun(); \ williamr@4: } williamr@4: williamr@4: /** williamr@4: Utility macro that can be used for specializing the default cleanup williamr@4: strategy class template TResourceCleanupStrategy for a particular williamr@4: class (typically a R-class). The default cleanup strategy for a class williamr@4: specified using DEFINE_CLEANUP_STRATEGY overrides any other cleanup williamr@4: strategy specified using DEFINE_CLEANUP_FUNCTION for that class. williamr@4: williamr@4: This macro must be used in the same namespace in which the R-class is williamr@4: defined. williamr@4: williamr@4: williamr@4: Utility macro that can be used for enabling single phase williamr@4: construction for CBase-derived classes. This is necessary because williamr@4: Symbian OS currently lacks the placement delete operator williamr@4: counterparts corresponding to the placement new operators that take williamr@4: a TLeave parameter (new(ELeave)), which will result in memory leaks williamr@4: if a class constructor leaves. williamr@4: williamr@4: This macro must be used within a public section of a class williamr@4: definition, if the single phase construction is part of the public williamr@4: interface of the class. williamr@4: williamr@4: Current Limitation CONSTRUCTORS_MAY_LEAVE is an unfortunate blight on the williamr@4: usability of single-phase construction, but we have yet to come up williamr@4: with a better alternative in the face of the legacy handling of williamr@4: ELeave. williamr@4: */ williamr@4: #define CONSTRUCTORS_MAY_LEAVE \ williamr@4: static void operator delete(TAny* aPtr) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete(aPtr); \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete(TAny*, TAny*) __NO_THROW \ williamr@4: { \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete(TAny* aPtr, TLeave) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete(aPtr); \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete(TAny* aPtr, TUint) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete(aPtr); \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete(TAny* aPtr, TLeave, TUint) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete(aPtr); \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete[](TAny* aPtr) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete[](aPtr); \ williamr@4: } \ williamr@4: \ williamr@4: static void operator delete[](TAny* aPtr, TLeave) __NO_THROW \ williamr@4: { \ williamr@4: ::operator delete[](aPtr); \ williamr@4: } williamr@4: williamr@4: williamr@4: // Implementation function. williamr@4: template williamr@4: void ManagedPopCleanupStackItem(T aIsManaged) williamr@4: { williamr@4: // CleanupStack-based cleanup is automatically triggered by a Leave, williamr@4: // so, in the case when __LEAVE_EQUALS_THROW__, williamr@4: // CleanupStack::PopAndDestroy must not be called again here williamr@4: #ifndef __GCCXML__ williamr@4: // for gccxml builds the std::uncaught_exception function is not listed in std name space williamr@4: // to supress GCCXML error williamr@4: if (!std::uncaught_exception()) williamr@4: { williamr@4: if (aIsManaged) williamr@4: { williamr@4: CleanupStack::PopAndDestroy(); williamr@4: } williamr@4: else williamr@4: { williamr@4: CleanupStack::Pop(); williamr@4: } williamr@4: } williamr@4: #endif williamr@4: } williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines the default cleanup strategy williamr@4: for managed resource class objects. williamr@4: williamr@4: The default cleanup strategy is to call the cleanup member function williamr@4: of the managed class, which is the Close() member function of the williamr@4: managed class, unless explicitly defined otherwise, for example by williamr@4: using the provided DEFINE_CLEANUP_FUNCTION macro. williamr@4: williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: class TResourceCleanupStrategy williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: CallCleanupFunction(aObjPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for managed williamr@4: resource class objects. This cleanup strategy calls the Close() williamr@4: member function of the managed class. williamr@4: williamr@4: @see LCleanedupHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TClose williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->Close(); williamr@4: } williamr@4: }; williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for managed williamr@4: resource class objects. This cleanup strategy calls the Release() williamr@4: member function of the managed class. williamr@4: williamr@4: @see LCleanedupHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TRelease williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->Release(); williamr@4: } williamr@4: }; williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for managed williamr@4: resource class objects. This cleanup strategy calls the Destroy() williamr@4: member function of the managed class. williamr@4: williamr@4: @see LCleanedupHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TDestroy williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->Destroy(); williamr@4: } williamr@4: }; williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for managed williamr@4: resource class objects. This cleanup strategy calls the Free() williamr@4: member function of the managed class. williamr@4: williamr@4: @see LCleanedupHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TFree williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->Free(); williamr@4: } williamr@4: }; williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for managed williamr@4: resource class objects. This cleanup strategy calls the williamr@4: ResetAndDestroy() member function of the managed class. williamr@4: williamr@4: @see LCleanedupHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedHandle to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TResetAndDestroy williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aObjPtr) williamr@4: { williamr@4: aObjPtr->ResetAndDestroy(); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines the default cleanup strategy williamr@4: for pointer types. For pointers to CBase-derived types, the williamr@4: default cleanup strategy is to call CBase::Delete with the managed williamr@4: pointer. For pointers to types that are not derived from CBase, williamr@4: the default cleanup strategy is to delete the managed pointer using williamr@4: non-array delete. williamr@4: williamr@4: @see LCleanedupPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TPtrCleanupStrategy williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aPtr) williamr@4: { williamr@4: delete aPtr; williamr@4: } williamr@4: williamr@4: static void Cleanup(CBase* aPtr) williamr@4: { williamr@4: CBase::Delete(aPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for pointer williamr@4: types. This cleanup strategy deletes the managed pointer by using williamr@4: non-array delete. williamr@4: williamr@4: @see LCleanedupPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TPointerDeleteStrategy williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aPtr) williamr@4: { williamr@4: delete aPtr; williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for williamr@4: pointers to CBase-derived types. This cleanup strategy calls williamr@4: CBase::Delete with the managed pointer. williamr@4: williamr@4: @see LCleanedupPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TCBaseDeleteStrategy williamr@4: { williamr@4: public: williamr@4: static void Cleanup(CBase* aPtr) williamr@4: { williamr@4: CBase::Delete(aPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines a cleanup strategy for pointer williamr@4: types. This cleanup strategy calls User::Free with the managed williamr@4: pointer. williamr@4: williamr@4: @see LCleanedupPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: @see LManagedPtr to which this strategy type may be supplied as williamr@4: an (optional) second tamplate parameter williamr@4: */ williamr@4: class TPointerFree williamr@4: { williamr@4: public: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: User::Free(aPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Strategy (policy) class that defines the default cleanup strategy williamr@4: for heap-allocated arrays. This cleanup strategy deallocates the williamr@4: managed array by using array delete. williamr@4: */ williamr@4: class TArrayDelete williamr@4: { williamr@4: public: williamr@4: template williamr@4: static void Cleanup(T* aPtr) williamr@4: { williamr@4: delete[] aPtr; williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: // enum type used for identifying the categories of managed pointer types williamr@4: enum TManagedPtrType williamr@4: { williamr@4: EPtrNonSpecial, williamr@4: EPtrCBaseDerived williamr@4: }; williamr@4: williamr@4: williamr@4: // macro used for determining whether a pointer is special williamr@4: #define IS_PTR_SPECIAL(T) IS_BASE_OF(CBase, T) williamr@4: williamr@4: williamr@4: // enum type used for identifying the categories of resource handle types williamr@4: enum TAutoHandleType williamr@4: { williamr@4: EAutoHandleNonSpecial, williamr@4: EAutoRHandleBaseDerived, williamr@4: EAutoHandleRBuf williamr@4: }; williamr@4: williamr@4: williamr@4: // macro used for determining whether a resource handle type is special williamr@4: #define IS_HANDLE_SPECIAL(T) IS_BASE_OF(RHandleBase, T) ? EAutoRHandleBaseDerived : ( (IS_SAME(RBuf8, T) || IS_SAME(RBuf16, T)) ? EAutoHandleRBuf : EAutoHandleNonSpecial ) williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. williamr@4: williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: template williamr@4: class LAutoHandleBase williamr@4: { williamr@4: protected: williamr@4: LAutoHandleBase() williamr@4: : iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LAutoHandleBase(const Param1& aParam1) williamr@4: : iHandle(aParam1), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LAutoHandleBase(Param1& aParam1) williamr@4: : iHandle(aParam1), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(const Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(const Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2), williamr@4: iEnabled(ETrue) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase& operator=(const U& aHandle) williamr@4: { williamr@4: iHandle = aHandle; williamr@4: iEnabled = ETrue; williamr@4: return *this; williamr@4: } williamr@4: williamr@4: T& Get() williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: const T& Get() const williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: T& operator*() williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: const T& operator*() const williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: T* operator->() williamr@4: { williamr@4: return &iHandle; williamr@4: } williamr@4: williamr@4: const T* operator->() const williamr@4: { williamr@4: return &iHandle; williamr@4: } williamr@4: williamr@4: T Unmanage() williamr@4: { williamr@4: iEnabled = EFalse; williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: TBool IsEnabled() const williamr@4: { williamr@4: return iEnabled; williamr@4: } williamr@4: williamr@4: void Disable() williamr@4: { williamr@4: iEnabled = EFalse; williamr@4: } williamr@4: williamr@4: void Swap(LAutoHandleBase& aAutoHandle) williamr@4: { williamr@4: ::Swap(iHandle, aAutoHandle.iHandle); williamr@4: ::Swap(iEnabled, aAutoHandle.iEnabled); williamr@4: } williamr@4: williamr@4: protected: williamr@4: T iHandle; williamr@4: TBool iEnabled; williamr@4: williamr@4: private: williamr@4: LAutoHandleBase(const LAutoHandleBase&); williamr@4: LAutoHandleBase& operator=(const LAutoHandleBase&); williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. Specialization for types derived from RHandleBase. williamr@4: */ williamr@4: template williamr@4: class LAutoHandleBase williamr@4: { williamr@4: protected: williamr@4: LAutoHandleBase() williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LAutoHandleBase(const Param1& aParam1) williamr@4: : iHandle(aParam1) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LAutoHandleBase(Param1& aParam1) williamr@4: : iHandle(aParam1) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(const Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(const Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase(Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : iHandle(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoHandleBase& operator=(const U& aHandle) williamr@4: { williamr@4: iHandle = aHandle; williamr@4: return *this; williamr@4: } williamr@4: williamr@4: T& Get() williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: const T& Get() const williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: T& operator*() williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: const T& operator*() const williamr@4: { williamr@4: return iHandle; williamr@4: } williamr@4: williamr@4: T* operator->() williamr@4: { williamr@4: return &iHandle; williamr@4: } williamr@4: williamr@4: const T* operator->() const williamr@4: { williamr@4: return &iHandle; williamr@4: } williamr@4: williamr@4: T Unmanage() williamr@4: { williamr@4: T handle = iHandle; williamr@4: iHandle.SetHandle(KNullHandle); williamr@4: return handle; williamr@4: } williamr@4: williamr@4: TBool IsEnabled() const williamr@4: { williamr@4: return iHandle.Handle() != KNullHandle; williamr@4: } williamr@4: williamr@4: void Disable() williamr@4: { williamr@4: iHandle.SetHandle(KNullHandle); williamr@4: } williamr@4: williamr@4: void Swap(LAutoHandleBase& aAutoHandle) williamr@4: { williamr@4: ::Swap(iHandle, aAutoHandle.iHandle); williamr@4: } williamr@4: williamr@4: protected: williamr@4: T iHandle; williamr@4: williamr@4: private: williamr@4: LAutoHandleBase(const LAutoHandleBase&); williamr@4: LAutoHandleBase& operator=(const LAutoHandleBase&); williamr@4: }; williamr@4: williamr@4: williamr@4: // N.B. RBuf8, RBuf16 and RBuf cannot be used with LManagedHandle and williamr@4: // LCleanedupHandle. Use LString or managed references instead. williamr@4: // The following specialization must not be used. williamr@4: template williamr@4: class LAutoHandleBase: protected T williamr@4: { williamr@4: private: williamr@4: LAutoHandleBase() williamr@4: { williamr@4: } williamr@4: williamr@4: ~LAutoHandleBase() williamr@4: { williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template for the creation and automatic management of williamr@4: resource handles (typically R-class instances) held in the data williamr@4: members of objects. williamr@4: williamr@4: @note This class should not used to define locals. See below for williamr@4: an explanation and links to management classes suitable for use in williamr@4: that context. williamr@4: williamr@4: This class template can be used to protect a resource handle of williamr@4: type T (typically an R-class instance) such that the instance of T williamr@4: protected is automatically cleaned up when the management object is williamr@4: destroyed; typically when the object containing it is deleted. williamr@4: williamr@4: By default, the cleanup action is to call the Close() member williamr@4: function of the managed handle. An alternative cleanup strategy may williamr@4: be selected by specifying a cleanup strategy template class in the williamr@4: optional second template parameter position. The most common williamr@4: alternative cleanup strategies are predefined. It is also possible williamr@4: to specialize the default cleanup action for a given class using williamr@4: the DEFINE_CLEANUP_FUNCTION macro. williamr@4: williamr@4: The constructors of this class never leave (unless construction of williamr@4: the underlying T instance can leave, which is rare), so data williamr@4: members defined with this type may be initialized safely during any williamr@4: phase of construction of the owning class. williamr@4: williamr@4: Any arguments supplied when initializing an instance of this class williamr@4: are automatically passed through to T's constructors. williamr@4: williamr@4: As a convenience, the methods of the managed pointer may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: class CComposite : public CBase williamr@4: { williamr@4: public: williamr@4: CONSTRUCTORS_MAY_LEAVE williamr@4: williamr@4: CComposite() williamr@4: { williamr@4: iFileServ->Connect() OR_LEAVE; williamr@4: iFile->Open(*iFileServ, ...); williamr@4: } williamr@4: williamr@4: ~CComposite() williamr@4: { williamr@4: // the handles are automatically closed williamr@4: } williamr@4: williamr@4: private: williamr@4: williamr@4: LManagedHandle iFileServ; williamr@4: LManagedHandle iFile; williamr@4: }; williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template simply relies on reliable williamr@4: execution of its destructor. If used for a local variable rather williamr@4: than a data member, cleanup will occur but out-of-order compared to williamr@4: objects protected using the LCleanupXxx variants or the williamr@4: CleanupStack directly. Therefore it is not recommended for use in williamr@4: that context. williamr@4: williamr@4: These management classes may be used as the basis for implementing williamr@4: leave-safe single-phase construction, since fully initialized williamr@4: data members protected in this way will get destroyed (so reliably williamr@4: triggering cleanup) if their containing classes leave during williamr@4: execution of their constructors. Note, however, that single-phase williamr@4: construction must be explicitly enabled in the containing class williamr@4: using the CONSTRUCTORS_MAY_LEAVE macro. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TClose which implements the default Close() calling cleanup strategy williamr@4: @see TResetAndDestroy which implements an alternative williamr@4: ResetAndDestroy() calling cleanup strategy williamr@4: @see TFree which implements an alternative Free() calling cleanup williamr@4: strategy williamr@4: @see TDestroy which implements an alternative Destroy() calling williamr@4: cleanup strategy williamr@4: @see TRelease which implements an alternative Release() calling cleanup strategy williamr@4: @see LCleanedupHandle which has the same interface, but uses the cleanup williamr@4: stack and is suitable for protecting locals williamr@4: @see CONSTRUCTORS_MAY_LEAVE williamr@4: */ williamr@4: template williamr@4: class LManagedHandle: protected LAutoHandleBase williamr@4: { williamr@4: typedef LAutoHandleBase LAutoHandleBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: /** williamr@4: Default constructor. williamr@4: */ williamr@4: LManagedHandle() williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LManagedHandle(const Param1& aParam1) williamr@4: : LAutoHandleBase(aParam1) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LManagedHandle(Param1& aParam1) williamr@4: : LAutoHandleBase(aParam1) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LManagedHandle(const Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LManagedHandle(const Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LManagedHandle(Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LManagedHandle(Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new resource to be managed. If the LManagedHandle object williamr@4: already contains a managed resource handle, then the managed williamr@4: resource is released using the specified cleanup strategy before williamr@4: assigning the new managed resource. williamr@4: williamr@4: @param aHandle a reference to a handle object of a type that can be assigned to a handle object of type T williamr@4: */ williamr@4: template williamr@4: LManagedHandle& operator=(const U& aHandle) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoHandleBase::operator=(aHandle); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor calls the cleanup function defined by the cleanup williamr@4: strategy with the contained resource handle object. williamr@4: */ williamr@4: ~LManagedHandle() williamr@4: { williamr@4: if (IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(&Get()); williamr@4: } williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, calls the cleanup williamr@4: function defined by the cleanup strategy with the managed resource williamr@4: handle object and then disables the automatic resource management williamr@4: for this object. The cleanup strategy is specified by the williamr@4: CleanupStrategy template template parameter. The default cleanup williamr@4: strategy is to call the cleanup member function on the contained williamr@4: resource handle object. which is a member function named Close(), williamr@4: unless explicitly defined otherwise for the class of the object, williamr@4: for example by using the provided DEFINE_CLEANUP_FUNCTION macro. williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(&Get()); williamr@4: LAutoHandleBase::Disable(); williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a copy of the resource handle. williamr@4: williamr@4: @return A copy of the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::Unmanage; williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoHandleBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a reference to the resource handle. williamr@4: williamr@4: @return A reference to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::Get; williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::operator*; williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::operator->; williamr@4: williamr@4: using LAutoHandleBase::Disable; williamr@4: williamr@4: void Swap(LManagedHandle& aManagedHandle) williamr@4: { williamr@4: LAutoHandleBase::Swap(aManagedHandle); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. williamr@4: williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: template williamr@4: class LAutoPtrBase williamr@4: { williamr@4: protected: williamr@4: LAutoPtrBase() williamr@4: : iPtr(NULL) williamr@4: { williamr@4: } williamr@4: williamr@4: explicit LAutoPtrBase(T* aPtr) williamr@4: : iPtr(aPtr) williamr@4: { williamr@4: } williamr@4: williamr@4: LAutoPtrBase& operator=(T* aPtr) williamr@4: { williamr@4: iPtr = aPtr; williamr@4: return *this; williamr@4: } williamr@4: williamr@4: T* Unmanage() williamr@4: { williamr@4: T* ptr = iPtr; williamr@4: iPtr = NULL; williamr@4: return ptr; williamr@4: } williamr@4: williamr@4: TBool IsEnabled() const williamr@4: { williamr@4: return iPtr != NULL; williamr@4: } williamr@4: williamr@4: T* Get() const williamr@4: { williamr@4: return iPtr; williamr@4: } williamr@4: williamr@4: T* operator->() const williamr@4: { williamr@4: return iPtr; williamr@4: } williamr@4: williamr@4: void Disable() williamr@4: { williamr@4: iPtr = NULL; williamr@4: } williamr@4: williamr@4: void Swap(LAutoPtrBase& aAutoPtr) williamr@4: { williamr@4: ::Swap(iPtr, aAutoPtr.iPtr); williamr@4: } williamr@4: williamr@4: protected: williamr@4: T* iPtr; williamr@4: williamr@4: private: williamr@4: LAutoPtrBase(const LAutoPtrBase&); williamr@4: LAutoPtrBase& operator=(const LAutoPtrBase&); williamr@4: }; williamr@4: williamr@4: williamr@4: // Cleanup traits class template williamr@4: template williamr@4: struct TPtrCleanupTraits williamr@4: { williamr@4: }; williamr@4: williamr@4: williamr@4: // Cleanup traits class template specialization for pointers to types williamr@4: // that are not derived from CBase williamr@4: template williamr@4: struct TPtrCleanupTraits williamr@4: { williamr@4: typedef T ManagedType; williamr@4: typedef T BaseManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: }; williamr@4: williamr@4: // Cleanup traits class template specialization for pointers to types williamr@4: // that are derived from CBase williamr@4: template williamr@4: struct TPtrCleanupTraits williamr@4: { williamr@4: typedef T ManagedType; williamr@4: typedef CBase BaseManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: }; williamr@4: williamr@4: // Cleanup traits class template specialization for pointers to types williamr@4: // that are derived from CBase and the default pointer cleanup williamr@4: // strategy (TPtrCleanupStrategy) williamr@4: template williamr@4: struct TPtrCleanupTraits williamr@4: { williamr@4: typedef CBase ManagedType; williamr@4: typedef CBase BaseManagedType; williamr@4: typedef TPtrCleanupStrategy CleanupStrategy; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. williamr@4: */ williamr@4: template williamr@4: class LManagedPtrBase: protected LAutoPtrBase::BaseManagedType> williamr@4: { williamr@4: typedef LAutoPtrBase::BaseManagedType> LAutoPtrBase; williamr@4: williamr@4: protected: williamr@4: typedef typename TPtrCleanupTraits::ManagedType ManagedType; williamr@4: typedef typename TPtrCleanupTraits::BaseManagedType BaseManagedType; williamr@4: typedef typename TPtrCleanupTraits::CleanupStrategy CleanupStrategy; williamr@4: williamr@4: LManagedPtrBase() williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LManagedPtrBase(U* aPtr) williamr@4: : LAutoPtrBase(aPtr) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: pointer. williamr@4: */ williamr@4: ~LManagedPtrBase() williamr@4: { williamr@4: if (IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(static_cast(iPtr)); williamr@4: } williamr@4: } williamr@4: williamr@4: template williamr@4: LManagedPtrBase& operator=(U* aPtr) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked for the managed pointer and the automatic williamr@4: resource management is then disabled. The underlying pointer is williamr@4: reset to NULL. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(static_cast(iPtr)); williamr@4: LAutoPtrBase::Disable(); williamr@4: } williamr@4: williamr@4: using LAutoPtrBase::Unmanage; williamr@4: williamr@4: using LAutoPtrBase::IsEnabled; williamr@4: williamr@4: using LAutoPtrBase::Get; williamr@4: williamr@4: using LAutoPtrBase::operator->; williamr@4: williamr@4: using LAutoPtrBase::Disable; williamr@4: williamr@4: using LAutoPtrBase::iPtr; williamr@4: williamr@4: void Swap(LManagedPtrBase& aManagedPtr) williamr@4: { williamr@4: LAutoPtrBase::Swap(aManagedPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides automatic management of pointers williamr@4: held in the data members of objects. williamr@4: williamr@4: @note This class should not used to define locals. See below for williamr@4: an explanation and links to management classes suitable for use in williamr@4: that context. williamr@4: williamr@4: This class template can be used to protect a pointer to type T such williamr@4: that the instance of T referred to is automatically cleaned up when williamr@4: the management object is destroyed; typically when the object williamr@4: containing it is deleted. williamr@4: williamr@4: By default, the cleanup action is to delete the managed pointer williamr@4: using a (non-array) delete operation. An alternative cleanup williamr@4: strategy can be specified using the optional CleanupStrategy class williamr@4: template parameter of the LManagedPtr class template. The most williamr@4: common alternative cleanup strategies are predefined williamr@4: (e.g. TPointerFree). williamr@4: williamr@4: The constructors of this class never leave, so data members defined with williamr@4: this type may be initialized safely during any phase of williamr@4: construction of the owning class. williamr@4: williamr@4: As a convenience, the methods of the managed pointer may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: class CComposite : public CBase williamr@4: { williamr@4: public: williamr@4: CONSTRUCTORS_MAY_LEAVE williamr@4: williamr@4: CComposite() williamr@4: : iComponent(CComponent::NewL()) williamr@4: { williamr@4: //... williamr@4: } williamr@4: williamr@4: ~CComposite() williamr@4: { williamr@4: // the pointer to the CComponent object is automatically williamr@4: // deleted williamr@4: } williamr@4: williamr@4: private: williamr@4: LManagedPtr iComponent; williamr@4: }; williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template simply relies on reliable williamr@4: execution of its destructor. If used for a local variable rather williamr@4: than a data member, cleanup will occur but out-of-order compared to williamr@4: objects protected using the LCleanupXxx variants or the williamr@4: CleanupStack directly. Therefore it is not recommended for use in williamr@4: that context. williamr@4: williamr@4: These management classes may be used as the basis for implementing williamr@4: leave-safe single-phase construction, since fully initialized williamr@4: data members protected in this way will get destroyed (so reliably williamr@4: triggering cleanup) if their containing classes leave during williamr@4: execution of their constructors. Note, however, that single-phase williamr@4: construction must be explicitly enabled in the containing class williamr@4: using the CONSTRUCTORS_MAY_LEAVE macro. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TPointerDelete which implements the default deleting cleanup strategy williamr@4: @see TPointerFree which implements the alternative User::Free() cleanup strategy williamr@4: @see LCleanedupPtr which has the same interface, but uses the cleanup williamr@4: stack and is suitable for protecting locals williamr@4: @see CONSTRUCTORS_MAY_LEAVE williamr@4: */ williamr@4: template williamr@4: class LManagedPtr: protected LManagedPtrBase williamr@4: { williamr@4: typedef LManagedPtrBase LManagedPtrBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: williamr@4: /** williamr@4: Default constructor. Constructs an empty LManagedPtr object. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: LManagedPtr() williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Explicit constructor template. Constructs a LManagedPtr object williamr@4: that manages the pointer aPtr of a type convertible to T* that can williamr@4: be cleaned up using the cleanup strategy of the LManagedPtr class. williamr@4: The default cleanup strategy is to delete the pointer to a williamr@4: heap-allocated object by using non-array delete. Alternative williamr@4: cleanup strategies can be specified by using the CleanupStrategy williamr@4: template parameter of the LManagedPtr class template. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is of a type convertible to T* and can be cleaned up williamr@4: using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: explicit LManagedPtr(T* aPtr) williamr@4: : LManagedPtrBase(aPtr) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: pointer. williamr@4: */ williamr@4: williamr@4: williamr@4: /** williamr@4: Assigns a new pointer to be managed. The new pointer must be of a williamr@4: type convertible to T* and it must be possible to use the cleanup williamr@4: strategy of the LManagedPtr object for the cleanup of the new williamr@4: managed pointer. If the LManagedPtr object already contains a williamr@4: managed pointer, then the cleanup strategy is invoked with the williamr@4: managed pointer before assigning the new managed pointer. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is a pointer of a type that is convertible to T* and can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: LManagedPtr& operator=(T* aPtr) williamr@4: { williamr@4: LManagedPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new pointer to be managed. The new pointer must be of a williamr@4: type convertible to T* and it must be possible to use the cleanup williamr@4: strategy of the LManagedPtr object for the cleanup of the new williamr@4: managed pointer. If the LManagedPtr object already contains a williamr@4: managed pointer, then the cleanup strategy is invoked with the williamr@4: managed pointer before assigning the new managed pointer. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is a pointer of a type that is convertible to T* and can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: template williamr@4: LManagedPtr& operator=(U* aPtr) williamr@4: { williamr@4: LManagedPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: using LManagedPtrBase::ReleaseResource; williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a pointer to the object of type T. williamr@4: williamr@4: @return A pointer to the object of type T. williamr@4: */ williamr@4: T* Unmanage() williamr@4: { williamr@4: return static_cast(LManagedPtrBase::Unmanage()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LManagedPtrBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a pointer to the managed object of type T. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: T* Get() const williamr@4: { williamr@4: return static_cast(iPtr); williamr@4: } williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: T& operator*() const williamr@4: { williamr@4: return *(static_cast(iPtr)); williamr@4: } williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: T* operator->() const williamr@4: { williamr@4: return static_cast(iPtr); williamr@4: } williamr@4: williamr@4: williamr@4: // Implementation type - do not use williamr@4: typedef typename LManagedPtrBase::BaseManagedType* LManagedPtr::*TUnspecifiedBoolType; williamr@4: williamr@4: /** williamr@4: Conversion operator that enables LCleanedupPtr objects to be used williamr@4: in boolean contexts. williamr@4: williamr@4: @return An unspecified value of an unspecified type convertible to williamr@4: boolean, which has a boolean value equal to Get() != NULL williamr@4: */ williamr@4: operator TUnspecifiedBoolType() williamr@4: { williamr@4: return iPtr ? &LManagedPtr::iPtr : NULL; williamr@4: } williamr@4: williamr@4: williamr@4: using LManagedPtrBase::Disable; williamr@4: williamr@4: void Swap(LManagedPtr& aManagedPtr) williamr@4: { williamr@4: LManagedPtrBase::Swap(aManagedPtr); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LManagedPtrBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: // function template used for comparing two LManagedPtr-managed williamr@4: // pointers for equality williamr@4: template williamr@4: TBool operator==(const LManagedPtr& aPtr1, const LManagedPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() == aPtr2.Get(); williamr@4: } williamr@4: williamr@4: // function template used for comparing two LManagedPtr-managed williamr@4: // pointers for inequality williamr@4: template williamr@4: TBool operator!=(const LManagedPtr& aPtr1, const LManagedPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() != aPtr2.Get(); williamr@4: } williamr@4: williamr@4: // function template used for testing the ordering of two williamr@4: // LManagedPtr-managed pointers williamr@4: template williamr@4: TBool operator<(const LManagedPtr& aPtr1, const LManagedPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() < aPtr2.Get(); williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides automatic management of arrays. Such williamr@4: managed arrays can be data members of composite classes. williamr@4: williamr@4: @note This class should not used to define locals. See below for williamr@4: an explanation and links to management classes suitable for use in williamr@4: that context. williamr@4: williamr@4: @par williamr@4: williamr@4: @note This class can only be used with raw arrays, which are used williamr@4: only rarely on Symbian OS. Instances of Symbian array container williamr@4: classes (e.g. RArray, RPointerArray) should be managed using the williamr@4: automatic management template classes appropriate for the array's williamr@4: type (LManagedHandle template classes for Symbian R arrays or williamr@4: LManagedPtr template classes for Symbian C arrays). williamr@4: williamr@4: This class template can be used to protect a heap-allocated array williamr@4: of objects of type T such that the managed array is automatically williamr@4: deallocated when the management object is destroyed. williamr@4: williamr@4: The default cleanup strategy is to deallocate the managed array williamr@4: using arrray delete (delete[]), assuming that the array is williamr@4: heap-allocated. An alternative cleanup strategy can be selected by williamr@4: specifying a cleanup strategy template class as the optional second williamr@4: template argument (corresponding to the CleanupStrategy template williamr@4: parameter). williamr@4: williamr@4: The constructors of this class never leave, so data members defined with williamr@4: this type may be initialized safely during any phase of williamr@4: construction of the owning class. williamr@4: williamr@4: As a convenience, the elements of the managed array may be accessed williamr@4: via "[]" notation directly on the management object. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: williamr@4: Example: williamr@4: @code williamr@4: class CComposite : public CBase williamr@4: { williamr@4: public: williamr@4: CONSTRUCTORS_MAY_LEAVE williamr@4: williamr@4: CComposite() williamr@4: : iComponents(new(ELeave) CComponent[KNumComponents]) williamr@4: { williamr@4: //... williamr@4: } williamr@4: williamr@4: ~CComposite() williamr@4: { williamr@4: // the array is automatically deleted williamr@4: } williamr@4: williamr@4: private: williamr@4: LManagedArray iComponents; williamr@4: }; williamr@4: @endcode williamr@4: williamr@4: williamr@4: Behind the scenes, this class template simply relies on reliable williamr@4: execution of its destructor. If used for a local variable rather williamr@4: than a data member, cleanup will occur but out-of-order compared to williamr@4: objects protected using the LCleanupXxx variants or the williamr@4: CleanupStack directly. Therefore it is not recommended for use in williamr@4: that context. williamr@4: williamr@4: These management classes may be used as the basis for implementing williamr@4: leave-safe single-phase construction, since fully initialized williamr@4: data members protected in this way will get destroyed (so reliably williamr@4: triggering cleanup) if their containing classes leave during williamr@4: execution of their constructors. Note, however, that single-phase williamr@4: construction must be explicitly enabled in the containing class williamr@4: using the CONSTRUCTORS_MAY_LEAVE macro. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see LCleanedupArray which has the same interface, but uses the cleanup williamr@4: stack and is suitable for protecting locals williamr@4: @see CONSTRUCTORS_MAY_LEAVE williamr@4: */ williamr@4: template williamr@4: class LManagedArray: protected LAutoPtrBase williamr@4: { williamr@4: typedef LAutoPtrBase LAutoPtrBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: /** williamr@4: Default constructor. Constructs an empty LManagedArray object. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: LManagedArray() williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Explicit constructor. Constructs a LManagedArray object that williamr@4: manages an array of objects of type T that can be cleaned up using williamr@4: the cleanup strategy of the LManagedArray class. The default williamr@4: cleanup strategy is to deallocate the managed array by using array williamr@4: delete (delete[]), assuming that the array is heap-allocated. williamr@4: Alternative cleanup strategies can be specified by using the williamr@4: CleanupStrategy template parameter of the LManagedArray class williamr@4: template. williamr@4: williamr@4: @param aPtr A pointer to the first element of an array of objects williamr@4: of type T - array that can be cleaned up using the cleanup strategy williamr@4: of the the LManagedArray class. williamr@4: williamr@4: @pre The array can be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: explicit LManagedArray(T* aPtr) williamr@4: : LAutoPtrBase(aPtr) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: pointer. williamr@4: */ williamr@4: ~LManagedArray() williamr@4: { williamr@4: if (LAutoPtrBase::IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: } williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new array of objects of type T to be managed. It needs williamr@4: to be possible use the cleanup strategy of the LManagedArray object williamr@4: for the cleanup of the new managed array. The default cleanup williamr@4: strategy is to delete the heap-allocated array by using array williamr@4: delete (delete[]). If the LManagedArray object already manages an williamr@4: array, then the cleanup strategy is invoked with the managed array williamr@4: before assigning the new managed array. williamr@4: williamr@4: @param aPtr A pointer to the first element of the array of objects williamr@4: of type T - array that can be cleaned up using the cleanup williamr@4: strategy. williamr@4: williamr@4: @pre The new array to be managed can be cleaned up using the williamr@4: cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: LManagedArray& operator=(T* aPtr) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked for the managed pointer and the automatic williamr@4: resource management is then disabled. The underlying pointer is williamr@4: reset to NULL. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!LAutoPtrBase::IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: LAutoPtrBase::Disable(); williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a pointer to the first element of the array of objects of williamr@4: type T. williamr@4: williamr@4: @return A pointer to the first element of the array of objects of williamr@4: type T. williamr@4: */ williamr@4: T* Unmanage() williamr@4: { williamr@4: return static_cast(LAutoPtrBase::Unmanage()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoPtrBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a pointer to the first element of the managed array of williamr@4: objects of type T. williamr@4: williamr@4: @return A pointer to the first element of the managed array of williamr@4: objects of type T. williamr@4: */ williamr@4: using LAutoPtrBase::Get; williamr@4: williamr@4: /** williamr@4: Overloaded subscript operator. williamr@4: williamr@4: @return A reference to the object of type T at the position aIndex. williamr@4: */ williamr@4: T& operator[](TInt aIndex) const williamr@4: { williamr@4: return iPtr[aIndex]; williamr@4: } williamr@4: williamr@4: using LAutoPtrBase::Disable; williamr@4: williamr@4: void Swap(LManagedArray& aArray) williamr@4: { williamr@4: LAutoPtrBase::Swap(aArray); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LAutoPtrBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. williamr@4: williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: template williamr@4: class LAutoRefBase williamr@4: { williamr@4: protected: williamr@4: template williamr@4: explicit LAutoRefBase(U& aRef) williamr@4: : iPtr(&aRef) williamr@4: { williamr@4: } williamr@4: williamr@4: template williamr@4: LAutoRefBase& operator=(U& aRef) williamr@4: { williamr@4: iPtr = &aRef; williamr@4: return *this; williamr@4: } williamr@4: williamr@4: T& Unmanage() williamr@4: { williamr@4: T* ptr = iPtr; williamr@4: iPtr = NULL; williamr@4: return *ptr; williamr@4: } williamr@4: williamr@4: TBool IsEnabled() const williamr@4: { williamr@4: return iPtr != NULL; williamr@4: } williamr@4: williamr@4: T& Get() const williamr@4: { williamr@4: return *iPtr; williamr@4: } williamr@4: williamr@4: T& operator*() const williamr@4: { williamr@4: return *iPtr; williamr@4: } williamr@4: williamr@4: T* operator->() const williamr@4: { williamr@4: return iPtr; williamr@4: } williamr@4: williamr@4: void Disable() williamr@4: { williamr@4: iPtr = NULL; williamr@4: } williamr@4: williamr@4: void Swap(LAutoRefBase& aAutoRef) williamr@4: { williamr@4: ::Swap(iPtr, aAutoRef.iPtr); williamr@4: } williamr@4: williamr@4: protected: williamr@4: T* iPtr; williamr@4: williamr@4: private: williamr@4: LAutoRefBase(const LAutoRefBase&); williamr@4: LAutoRefBase& operator=(const LAutoRefBase&); williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides automatic management of references williamr@4: to resource handles (often R-class instances) held in the data williamr@4: members of objects. williamr@4: williamr@4: @note This class should not used to define locals. See below for williamr@4: an explanation and links to management classes suitable for use in williamr@4: that context. williamr@4: williamr@4: Unlike LManagedHandle which creates a fresh instance of its managed williamr@4: type, this class template can be used to protect an existing williamr@4: resource handle of type T (typically an R-class instance). The williamr@4: instance of T referred to has a cleanup operation run on it williamr@4: automatically when the management object is destroyed; typically williamr@4: when the object containing it is deleted. williamr@4: williamr@4: By default, the cleanup action is to call the Close() member williamr@4: function of the referenced handle. An alternative cleanup strategy may williamr@4: be selected by specifying a cleanup strategy template class in the williamr@4: optional second template parameter position. The most common williamr@4: alternative cleanup strategies are predefined. It is also possible williamr@4: to specialize the default cleanup action for a given class using williamr@4: the DEFINE_CLEANUP_FUNCTION macro. williamr@4: williamr@4: The constructors of this class never leave, so data members defined with williamr@4: this type may be initialized safely during any phase of williamr@4: construction of the owning class. williamr@4: williamr@4: As a convenience, the methods of the managed pointer may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: class CComposite : public CBase williamr@4: { williamr@4: public: williamr@4: CONSTRUCTORS_MAY_LEAVE williamr@4: williamr@4: // An existing RFs instance is given to us to reuse, but williamr@4: // we are responsible for calling Close() when we're done williamr@4: CComposite(RFs& aFs) williamr@4: : iFileServ(aFs) williamr@4: { williamr@4: iFileServ->Connect() OR_LEAVE; williamr@4: iFile->Open(*iFileServ, ...); williamr@4: } williamr@4: williamr@4: ~CComposite() williamr@4: { williamr@4: // the handles are automatically closed williamr@4: } williamr@4: williamr@4: private: williamr@4: williamr@4: LManagedRef iFileServ; williamr@4: LManagedHandle iFile; williamr@4: }; williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template simply relies on reliable williamr@4: execution of its destructor. If used for a local variable rather williamr@4: than a data member, cleanup will occur but out-of-order compared to williamr@4: objects protected using the LCleanupXxx variants or the williamr@4: CleanupStack directly. Therefore it is not recommended for use in williamr@4: that context. williamr@4: williamr@4: These management classes may be used as the basis for implementing williamr@4: leave-safe single-phase construction, since fully initialized williamr@4: data members protected in this way will get destroyed (so reliably williamr@4: triggering cleanup) if their containing classes leave during williamr@4: execution of their constructors. Note, however, that single-phase williamr@4: construction must be explicitly enabled in the containing class williamr@4: using the CONSTRUCTORS_MAY_LEAVE macro. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TClose which implements the default Close() calling cleanup strategy williamr@4: @see TResetAndDestroy which implements an alternative williamr@4: ResetAndDestroy() calling cleanup strategy williamr@4: @see TFree which implements an alternative Free() calling cleanup williamr@4: strategy williamr@4: @see TDestroy which implements an alternative Destroy() calling williamr@4: cleanup strategy williamr@4: @see TRelease which implements an alternative Release() calling williamr@4: cleanup strategy williamr@4: @see LCleanedupRef which has the same interface, but uses the cleanup williamr@4: stack and is suitable for protecting locals williamr@4: @see LManagedHandle which has a similar interface but creates a fresh williamr@4: local instance of T williamr@4: @see CONSTRUCTORS_MAY_LEAVE williamr@4: */ williamr@4: template williamr@4: class LManagedRef: protected LAutoRefBase williamr@4: { williamr@4: typedef LAutoRefBase LAutoRefBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: /** williamr@4: Explicit constructor. williamr@4: */ williamr@4: template williamr@4: explicit LManagedRef(U& aRef) williamr@4: : LAutoRefBase(aRef) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: reference. williamr@4: */ williamr@4: ~LManagedRef() williamr@4: { williamr@4: if (LAutoRefBase::IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: } williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new reference to be managed. If the LManagedRef williamr@4: object already contains a managed reference, then the specified williamr@4: cleanup strategy is invoked for the managed reference before williamr@4: assigning the new managed reference. williamr@4: */ williamr@4: template williamr@4: LManagedRef& operator=(U& aRef) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoRefBase::operator=(aRef); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked for the managed reference and the automatic williamr@4: resource management is then disabled for this object. williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!LAutoRefBase::IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: LAutoRefBase::Disable(); williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a reference to the object of type T. williamr@4: williamr@4: @return A reference to the object of type T. williamr@4: */ williamr@4: using LAutoRefBase::Unmanage; williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoRefBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a reference to the managed object of type T. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::Get; williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::operator*; williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::operator->; williamr@4: williamr@4: using LAutoRefBase::Disable; williamr@4: williamr@4: void Swap(LManagedRef& aRef) williamr@4: { williamr@4: LAutoRefBase::Swap(aRef); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LAutoRefBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template for the creation and CleanupStack-based williamr@4: local-scope automatic management of resource handles (typically williamr@4: instances of R-classes). williamr@4: williamr@4: @note This class can only be used to define locals, never williamr@4: data members. See below for an explanation and links to management williamr@4: classes suitable for use in different contexts. It should never be williamr@4: used in the same function as code that uses the CleanupStack API williamr@4: directly. williamr@4: williamr@4: This class template can be used to create and protect a resource williamr@4: handle of type T (typically a R-class) such that the instance of T williamr@4: referred to is automatically cleaned up when either of the williamr@4: following occur: williamr@4: williamr@4: - The referring local variable goes out of scope normally williamr@4: - The referring local variable goes out of scope due to an williamr@4: untrapped leave causing the scope to be exited non-locally williamr@4: williamr@4: By default, the cleanup action is to call the Close() member williamr@4: function of the managed handle. An alternative cleanup strategy may williamr@4: be selected by specifying a cleanup strategy template class in the williamr@4: optional second template parameter position. The most common williamr@4: alternative cleanup strategies are predefined. It is also possible williamr@4: to specialize the default cleanup action for a given class using williamr@4: the DEFINE_CLEANUP_FUNCTION macro. williamr@4: williamr@4: The constructors of this class may leave. williamr@4: williamr@4: Any arguments supplied when initializing an instance of this class williamr@4: are automatically passed through to T's constructors. williamr@4: williamr@4: As a convenience, the methods of the managed handle may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: // block scope example williamr@4: { williamr@4: LCleanedupHandle obj; williamr@4: obj->DoSomethingL(); // leave-safe williamr@4: if (obj->Finished()) williamr@4: return; // RClosable::Close is invoked automatically williamr@4: obj->DoSomethingElseL(); // leave-safe williamr@4: // RClosable::Close is invoked automatically williamr@4: } williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template is implemented in terms of williamr@4: the thread-local CleanupStack, restricting its use to locals on the williamr@4: stack. This use of the CleanupStack ensures a consistent cleanup williamr@4: order between functions that call one another, even if they use williamr@4: different cleanup idioms. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TClose which implements the default Close() calling cleanup strategy williamr@4: @see TResetAndDestroy which implements an alternative williamr@4: ResetAndDestroy() calling cleanup strategy williamr@4: @see TFree which implements an alternative Free() calling cleanup williamr@4: strategy williamr@4: @see TDestroy which implements an alternative Destroy() calling williamr@4: cleanup strategy williamr@4: @see TRelease which implements an alternative Release() calling cleanup strategy williamr@4: @see LManagedHandle which has the same interface, but does not use the cleanup williamr@4: stack and is suitable for protecting the data members of classes williamr@4: */ williamr@4: template williamr@4: class LCleanedupHandle: protected LAutoHandleBase williamr@4: { williamr@4: typedef LAutoHandleBase LAutoHandleBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: williamr@4: /** williamr@4: Default constructor. williamr@4: */ williamr@4: LCleanedupHandle() williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LCleanedupHandle(const Param1& aParam1) williamr@4: : LAutoHandleBase(aParam1) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LCleanedupHandle(Param1& aParam1) williamr@4: : LAutoHandleBase(aParam1) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: LCleanedupHandle(const Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: LCleanedupHandle(const Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: LCleanedupHandle(Param1& aParam1, williamr@4: const Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: LCleanedupHandle(Param1& aParam1, williamr@4: Param2& aParam2) williamr@4: : LAutoHandleBase(aParam1, williamr@4: aParam2) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: williamr@4: ~LCleanedupHandle() williamr@4: { williamr@4: ManagedPopCleanupStackItem(IsEnabled()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new resource to be managed. If the LCleanedupHandle williamr@4: object already contains a managed resource handle, then the managed williamr@4: resource is released using the specified cleanup strategy before williamr@4: assigning the new managed resource. williamr@4: */ williamr@4: template williamr@4: LCleanedupHandle& operator=(const U& aHandle) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoHandleBase::operator=(aHandle); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, calls the cleanup williamr@4: function defined by the cleanup strategy with the managed resource williamr@4: handle object and then disables the automatic resource management williamr@4: for this object. The cleanup strategy is specified by the williamr@4: CleanupStrategy template template parameter. The default cleanup williamr@4: strategy is to call the cleanup member function on the contained williamr@4: resource handle object. which is a member function named Close(), williamr@4: unless explicitly defined otherwise for the class of the object, williamr@4: for example by using the provided DEFINE_CLEANUP_FUNCTION macro. williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(&Get()); williamr@4: LAutoHandleBase::Disable(); williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this obkect and williamr@4: returns a copy of the resource handle. williamr@4: williamr@4: @return A copy of the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::Unmanage; williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoHandleBase::IsEnabled; williamr@4: williamr@4: williamr@4: /** williamr@4: Returns a reference to the resource handle. williamr@4: williamr@4: @return A reference to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::Get; williamr@4: williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::operator*; williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the resource handle. williamr@4: */ williamr@4: using LAutoHandleBase::operator->; williamr@4: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: LCleanedupHandle* autoh = static_cast(aPtr); williamr@4: williamr@4: if (autoh->IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(&autoh->Get()); williamr@4: } williamr@4: } williamr@4: williamr@4: using LAutoHandleBase::Disable; williamr@4: williamr@4: void Swap(LCleanedupHandle& aCleanedupHandle) williamr@4: { williamr@4: LAutoHandleBase::Swap(aCleanedupHandle); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: Implementation base class - not designed for public inheritance or williamr@4: direct use. williamr@4: williamr@4: @internalComponent williamr@4: */ williamr@4: // Not for Client Use , Only to be used Internally. williamr@4: template williamr@4: class LCleanedupPtrBase: protected LAutoPtrBase::BaseManagedType> williamr@4: { williamr@4: typedef LAutoPtrBase::BaseManagedType> LAutoPtrBase; williamr@4: williamr@4: protected: williamr@4: typedef typename TPtrCleanupTraits::ManagedType ManagedType; williamr@4: typedef typename TPtrCleanupTraits::BaseManagedType BaseManagedType; williamr@4: typedef typename TPtrCleanupTraits::CleanupStrategy CleanupStrategy; williamr@4: williamr@4: LCleanedupPtrBase() williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: template williamr@4: explicit LCleanedupPtrBase(U* aPtr) williamr@4: : LAutoPtrBase(aPtr) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: ~LCleanedupPtrBase() williamr@4: { williamr@4: ManagedPopCleanupStackItem(LAutoPtrBase::IsEnabled()); williamr@4: } williamr@4: williamr@4: template williamr@4: LCleanedupPtrBase& operator=(U* aPtr) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!LAutoPtrBase::IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(static_cast(iPtr)); williamr@4: LAutoPtrBase::Disable(); williamr@4: } williamr@4: williamr@4: using LAutoPtrBase::Unmanage; williamr@4: williamr@4: using LAutoPtrBase::IsEnabled; williamr@4: williamr@4: using LAutoPtrBase::Get; williamr@4: williamr@4: using LAutoPtrBase::operator->; williamr@4: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: LCleanedupPtrBase* cleanupPtr = static_cast(aPtr); williamr@4: williamr@4: if (cleanupPtr->IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(static_cast(cleanupPtr->iPtr)); williamr@4: } williamr@4: } williamr@4: williamr@4: using LAutoPtrBase::iPtr; williamr@4: williamr@4: void Swap(LCleanedupPtrBase& aCleanedupPtr) williamr@4: { williamr@4: LAutoPtrBase::Swap(aCleanedupPtr); williamr@4: } williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides CleanupStack-based local-scope williamr@4: automatic management of pointers. williamr@4: williamr@4: @note This class can only be used to define locals, never williamr@4: data members. See below for an explanation and links to management williamr@4: classes suitable for use in different contexts. It should never be williamr@4: used in the same function as code that uses the CleanupStack API williamr@4: directly williamr@4: williamr@4: This class template can be used to protect a pointer to type T such williamr@4: that the instance of T referred to is automatically cleaned up williamr@4: when either of the following occur: williamr@4: williamr@4: - The referring local variable goes out of scope normally williamr@4: - The referring local variable goes out of scope due to an williamr@4: untrapped leave causing the scope to be exited non-locally williamr@4: williamr@4: By default, the cleanup action is to delete the managed pointer williamr@4: using non-array delete. An alternative cleanup strategy may be williamr@4: selected by specifying a cleanup strategy template class in the williamr@4: optional second template parameter position. The most common williamr@4: alternative cleanup strategies are predefined. williamr@4: williamr@4: The constructors of this class may leave. williamr@4: williamr@4: As a convenience, the methods of the managed pointer may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: // block scope example williamr@4: { williamr@4: LCleanedupPtr autop(new(ELeave) CDynamic); williamr@4: autop->DoSomethingL(); // leave-safe williamr@4: if (autop->Finished()) williamr@4: return; // the pointer is deleted automatically when exiting from scope williamr@4: autop->DoSomethingElseL(); // leave-safe williamr@4: // the pointer is deleted automatically when exiting from scope williamr@4: } williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template is implemented in terms of williamr@4: the thread-local CleanupStack, restricting its use to locals on the williamr@4: stack. This use of the CleanupStack ensures a consistent cleanup williamr@4: order between functions that call one another, even if they use williamr@4: different cleanup idioms. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TPointerDelete which implements the default deleting cleanup strategy williamr@4: @see TPointerFree which implements the alternative User::Free() cleanup strategy williamr@4: @see LManagedPtr which has the same interface, but does not use the cleanup williamr@4: stack and is suitable for protecting the data members of classes williamr@4: */ williamr@4: template williamr@4: class LCleanedupPtr: protected LCleanedupPtrBase williamr@4: { williamr@4: typedef LCleanedupPtrBase LCleanedupPtrBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: williamr@4: /** williamr@4: Default constructor. Constructs an empty LCleanedupPtr object. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: LCleanedupPtr() williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Explicit constructor template. Constructs a LCleanedupPtr object williamr@4: that manages the pointer aPtr of a type convertible to T* that can williamr@4: be cleaned up using the cleanup strategy of the LCleanedupPtr williamr@4: class. The default cleanup strategy is to delete the pointer to a williamr@4: heap-allocated object by using non-array delete. Alternative williamr@4: cleanup strategies can be specified by using the CleanupStrategy williamr@4: template parameter of the LCleanedupPtr class template. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is of a type convertible to T* and can be cleaned up williamr@4: using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: explicit LCleanedupPtr(T* aPtr) williamr@4: : LCleanedupPtrBase(aPtr) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new pointer to be managed. The new pointer must be of a williamr@4: type convertible to T* and it must be possible to use the cleanup williamr@4: strategy of the LCleanedupPtr object for the cleanup of the new williamr@4: managed pointer. If the LCleanedupPtr object already contains a williamr@4: managed pointer, then the cleanup strategy is invoked with the williamr@4: managed pointer before assigning the new managed pointer. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is a pointer of a type that is convertible to T* and can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: LCleanedupPtr& operator=(T* aPtr) williamr@4: { williamr@4: LCleanedupPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new pointer to be managed. The new pointer must be of a williamr@4: type convertible to T* and it must be possible to use the cleanup williamr@4: strategy of the LCleanedupPtr object for the cleanup of the new williamr@4: managed pointer. If the LCleanedupPtr object already contains a williamr@4: managed pointer, then the cleanup strategy is invoked with the williamr@4: managed pointer before assigning the new managed pointer. williamr@4: williamr@4: @param aPtr A pointer of a type that is convertible to T* that can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @pre aPtr is a pointer of a type that is convertible to T* and can williamr@4: be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: template williamr@4: LCleanedupPtr& operator=(U* aPtr) williamr@4: { williamr@4: LCleanedupPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked with the managed pointer and the automatic williamr@4: resource management is then disabled. The underlying pointer is williamr@4: reset to NULL. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: using LCleanedupPtrBase::ReleaseResource; williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a pointer to the object of type T. williamr@4: williamr@4: @return A pointer to the object of type T. williamr@4: */ williamr@4: T* Unmanage() williamr@4: { williamr@4: return static_cast(LCleanedupPtrBase::Unmanage()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LCleanedupPtrBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a pointer to the managed object of type T. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: T* Get() const williamr@4: { williamr@4: return static_cast(iPtr); williamr@4: } williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: T& operator*() const williamr@4: { williamr@4: return *(static_cast(iPtr)); williamr@4: } williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: T* operator->() const williamr@4: { williamr@4: return static_cast(iPtr); williamr@4: } williamr@4: williamr@4: // Implementation type - do not use williamr@4: typedef typename LCleanedupPtrBase::BaseManagedType* LCleanedupPtr::*TUnspecifiedBoolType; williamr@4: williamr@4: /** williamr@4: Conversion operator that enables LCleanedupPtr objects to be used williamr@4: in boolean contexts. williamr@4: williamr@4: @return An unspecified value of an unspecified type convertible to williamr@4: boolean, which has a boolean value equal to Get() != NULL williamr@4: */ williamr@4: operator TUnspecifiedBoolType() williamr@4: { williamr@4: return iPtr ? &LCleanedupPtr::iPtr : NULL; williamr@4: } williamr@4: williamr@4: using LCleanedupPtrBase::Disable; williamr@4: williamr@4: void Swap(LCleanedupPtr& aCleanedupPtr) williamr@4: { williamr@4: LCleanedupPtrBase::Swap(aCleanedupPtr); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LCleanedupPtrBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: // function template used for comparing two LCleanedupPtr-managed williamr@4: // pointers for equality williamr@4: template williamr@4: TBool operator==(const LCleanedupPtr& aPtr1, const LCleanedupPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() == aPtr2.Get(); williamr@4: } williamr@4: williamr@4: // function template used for comparing two LCleanedupPtr-managed williamr@4: // pointers for inequality williamr@4: template williamr@4: TBool operator!=(const LCleanedupPtr& aPtr1, const LCleanedupPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() != aPtr2.Get(); williamr@4: } williamr@4: williamr@4: // function template used for testing the ordering of two williamr@4: // LCleanedupPtr-managed pointers williamr@4: template williamr@4: TBool operator<(const LCleanedupPtr& aPtr1, const LCleanedupPtr& aPtr2) williamr@4: { williamr@4: return aPtr1.Get() < aPtr2.Get(); williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides CleanupStack-based local-scope williamr@4: automatic management of arrays. williamr@4: williamr@4: @note This class can only be used to define locals, never williamr@4: data members. See below for an explanation and links to management williamr@4: classes suitable for use in different contexts. It should never be williamr@4: used in the same function as code that uses the CleanupStack API williamr@4: directly williamr@4: williamr@4: @par williamr@4: williamr@4: @note This class can only be used with raw arrays, which are used williamr@4: only rarely on Symbian OS. Instances of Symbian array container williamr@4: classes (e.g. RArray, RPointerArray) should be managed using the williamr@4: automatic management template classes appropriate for the array's williamr@4: type (LCleanedupHandle template classes for Symbian R arrays or williamr@4: LCleanedupPtr template classes for Symbian C arrays). williamr@4: williamr@4: This class template can be used to protect a heap-allocated array williamr@4: of objects of type T such that the array of T referred to is williamr@4: automatically cleaned up when either of the following occur: williamr@4: williamr@4: - The referring local variable goes out of scope normally williamr@4: - The referring local variable goes out of scope due to an williamr@4: untrapped leave causing the scope to be exited non-locally williamr@4: williamr@4: The default cleanup strategy is to deallocate the managed array williamr@4: using arrray delete (delete[]), assuming that the array is williamr@4: heap-allocated. An alternative cleanup strategy can be selected by williamr@4: specifying a cleanup strategy template class as the optional second williamr@4: template argument (corresponding to the CleanupStrategy template williamr@4: parameter). williamr@4: williamr@4: The constructors of this class may leave. williamr@4: williamr@4: As a convenience, the elements of the managed array may be accessed williamr@4: via "[]" notation directly on the management object. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: @code williamr@4: // block scope example williamr@4: { williamr@4: LCleanedupArray arrayp(new(ELeave) TValue[KArraySize]); williamr@4: arrayp[0].DoSomethingL(); // leave-safe williamr@4: if (arrayp[0].Finished()) williamr@4: return; // the array is deleted automatically when exiting from scope williamr@4: arrayp[1].DoSomethingElseL(); // leave-safe williamr@4: // the array is deleted automatically when exiting from scope williamr@4: } williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template is implemented in terms of williamr@4: the thread-local CleanupStack, restricting its use to locals on the williamr@4: stack. This use of the CleanupStack ensures a consistent cleanup williamr@4: order between functions that call one another, even if they use williamr@4: different cleanup idioms. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see LManagedArray which has the same interface, but does not use williamr@4: the cleanup stack and is suitable for protecting the data members williamr@4: of classes williamr@4: */ williamr@4: template williamr@4: class LCleanedupArray: protected LAutoPtrBase williamr@4: { williamr@4: typedef LAutoPtrBase LAutoPtrBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: /** williamr@4: Default constructor. Constructs an empty LCleanedupArray object. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: LCleanedupArray() williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: /** williamr@4: Explicit constructor. Constructs a LCleanedupArray object that williamr@4: manages an array of objects of type T that can be cleaned up using williamr@4: the cleanup strategy of the LCleanedupArray class. The default williamr@4: cleanup strategy is to deallocate the heap-allocated array by using williamr@4: array delete. An alternative cleanup strategy can be selected by williamr@4: specifying a cleanup strategy template class as the optional second williamr@4: template argument (corresponding to the CleanupStrategy template williamr@4: parameter). williamr@4: williamr@4: @param aPtr A pointer to the first element of an array of objects williamr@4: of type T, array that can be cleaned up using the cleanup strategy williamr@4: of the the LCleanedupArray class. williamr@4: williamr@4: @pre The array can be cleaned up using the cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: explicit LCleanedupArray(T* aPtr) williamr@4: : LAutoPtrBase(aPtr) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: pointer. williamr@4: */ williamr@4: ~LCleanedupArray() williamr@4: { williamr@4: ManagedPopCleanupStackItem(LAutoPtrBase::IsEnabled()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new array of objects of type T to be managed. It needs williamr@4: to be be possible to use the cleanup strategy of the williamr@4: LCleanedupArray object for the cleanup of the new managed array. williamr@4: The default cleanup strategy is to delete the heap-allocated array williamr@4: by using array delete (delete[]). If the LCleanedupArray object williamr@4: already manages an array, then the cleanup strategy is invoked with williamr@4: the managed array before assigning the new managed array. williamr@4: williamr@4: @param aPtr A pointer to the first element of the array of objects williamr@4: of type T - array that can be cleaned up using the cleanup williamr@4: strategy. williamr@4: williamr@4: @pre The new array to be managed can be cleaned up using the williamr@4: cleanup strategy. williamr@4: williamr@4: @post Get() == aPtr williamr@4: */ williamr@4: LCleanedupArray& operator=(T* aPtr) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoPtrBase::operator=(aPtr); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked for the managed pointer and the automatic williamr@4: resource management is then disabled. The underlying pointer is williamr@4: reset to NULL. williamr@4: williamr@4: @post Get() == NULL williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!LAutoPtrBase::IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: iPtr = NULL; williamr@4: } williamr@4: williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a pointer to the first element of the array of objects of williamr@4: type T. williamr@4: williamr@4: @return A pointer to the first element of the array of objects of williamr@4: type T. williamr@4: */ williamr@4: using LAutoPtrBase::Unmanage; williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoPtrBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a pointer to the first element of the managed array of williamr@4: objects of type T. williamr@4: williamr@4: @return A pointer to the first element of the managed array of williamr@4: objects of type T. williamr@4: */ williamr@4: using LAutoPtrBase::Get; williamr@4: williamr@4: /** williamr@4: Overloaded subscript operator. williamr@4: williamr@4: @return A reference to the object of type T at the position aIndex. williamr@4: */ williamr@4: T& operator[](TInt aIndex) const williamr@4: { williamr@4: return iPtr[aIndex]; williamr@4: } williamr@4: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: LCleanedupArray* cleanupPtr = static_cast(aPtr); williamr@4: williamr@4: if (cleanupPtr->IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(cleanupPtr->iPtr); williamr@4: } williamr@4: } williamr@4: williamr@4: using LAutoPtrBase::Disable; williamr@4: williamr@4: void Swap(LCleanedupArray& aArray) williamr@4: { williamr@4: LAutoPtrBase::Swap(aArray); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LAutoPtrBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class template that provides CleanupStack-based local-scope williamr@4: automatic management of references to resource handles (often williamr@4: instances of R-classes). williamr@4: williamr@4: @note This class can only be used to define locals, never williamr@4: data members. See below for an explanation and links to management williamr@4: classes suitable for use in different contexts. It should never be williamr@4: used in the same function as code that uses the CleanupStack API williamr@4: directly. williamr@4: williamr@4: Unlike LCleanedupHandle which creates a fresh instance of its williamr@4: managed type, this class template can be used to reference and williamr@4: protect an existing resource handle of type T (typically an williamr@4: R-class). The instance of T referred to has a cleanup operation run williamr@4: on it automatically when either of the following occur: williamr@4: williamr@4: - The referring local variable goes out of scope normally williamr@4: - The referring local variable goes out of scope due to an williamr@4: untrapped leave causing the scope to be exited non-locally williamr@4: williamr@4: By default, the cleanup action is to call the Close() member williamr@4: function of the referenced handle. An alternative cleanup strategy williamr@4: may be selected by specifying a cleanup strategy template class in williamr@4: the optional second template parameter position. The most common williamr@4: alternative cleanup strategies are predefined. It is also possible williamr@4: to specialize the default cleanup action for a given class using williamr@4: the DEFINE_CLEANUP_FUNCTION macro. williamr@4: williamr@4: The constructors of this class may leave. williamr@4: williamr@4: As a convenience, the methods of the managed handle may be williamr@4: accessed via "->" notation directly on the management object, while williamr@4: "." notation is used to access the interface of the management williamr@4: object itself. Using "*" to dereference the management object williamr@4: yields a T&, and is often useful when passing the managed object as williamr@4: an argument. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Unmanage(), while cleanup may be forced at any time by calling williamr@4: ReleaseResource(). williamr@4: williamr@4: Example: williamr@4: @code williamr@4: // block scope example williamr@4: void DoWithClosable(RClosable& aObj) williamr@4: { williamr@4: LCleanedupRef obj(aObj); williamr@4: obj->DoSomethingL(); // leave-safe williamr@4: if (obj->Finished()) williamr@4: return; // RClosable::Close is invoked automatically williamr@4: obj->DoSomethingElseL(); // leave-safe williamr@4: // RClosable::Close is invoked automatically williamr@4: } williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template is implemented in terms of williamr@4: the thread-local CleanupStack, restricting its use to locals on the williamr@4: stack. This use of the CleanupStack ensures a consistent cleanup williamr@4: order between functions that call one another, even if they use williamr@4: different cleanup idioms. williamr@4: williamr@4: This class template together with the cleanup strategy class williamr@4: templates provide a template-based implementation of the Strategy williamr@4: design pattern (See also: Policy-based design). williamr@4: williamr@4: @see TClose which implements the default Close() calling cleanup strategy williamr@4: @see TResetAndDestroy which implements an alternative williamr@4: ResetAndDestroy() calling cleanup strategy williamr@4: @see TFree which implements an alternative Free() calling cleanup williamr@4: strategy williamr@4: @see TDestroy which implements an alternative Destroy() calling williamr@4: cleanup strategy williamr@4: @see TRelease which implements an alternative Release() calling williamr@4: cleanup strategy williamr@4: @see LManagedRef which has the same interface, but does not use williamr@4: the cleanup stack and is suitable for protecting the data members of williamr@4: classes williamr@4: @see LCleanedupHandle which has a similar interface but creates a williamr@4: fresh local instance of T williamr@4: */ williamr@4: template williamr@4: class LCleanedupRef: protected LAutoRefBase williamr@4: { williamr@4: typedef LAutoRefBase LAutoRefBase; williamr@4: williamr@4: public: williamr@4: typedef T ManagedType; williamr@4: typedef CleanupStrategyType CleanupStrategy; williamr@4: williamr@4: /** williamr@4: Explicit constructor. williamr@4: */ williamr@4: template williamr@4: explicit LCleanedupRef(U& aRef) williamr@4: : LAutoRefBase(aRef) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. When automatic resource management is enabled, the williamr@4: destructor invokes the specified cleanup strategy for the managed williamr@4: reference. williamr@4: */ williamr@4: ~LCleanedupRef() williamr@4: { williamr@4: ManagedPopCleanupStackItem(LAutoRefBase::IsEnabled()); williamr@4: } williamr@4: williamr@4: /** williamr@4: Assigns a new reference to be managed. If the LCleanedupRef williamr@4: object already contains a managed reference, then the specified williamr@4: cleanup strategy is invoked for the managed reference before williamr@4: assigning the new managed reference. williamr@4: */ williamr@4: template williamr@4: LCleanedupRef& operator=(U& aRef) williamr@4: { williamr@4: ReleaseResource(); williamr@4: LAutoRefBase::operator=(aRef); williamr@4: return *this; williamr@4: } williamr@4: williamr@4: /** williamr@4: If automatic resource management is enabled, the specified cleanup williamr@4: strategy is invoked for the managed reference and the automatic williamr@4: resource management is then disabled. williamr@4: */ williamr@4: void ReleaseResource() williamr@4: { williamr@4: if (!LAutoRefBase::IsEnabled()) williamr@4: return; williamr@4: williamr@4: CleanupStrategy::Cleanup(iPtr); williamr@4: iPtr = NULL; williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the automatic resource management for this object and williamr@4: returns a reference to the object of type T. williamr@4: williamr@4: @return A reference to the object of type T. williamr@4: */ williamr@4: using LAutoRefBase::Unmanage; williamr@4: williamr@4: /** williamr@4: Returns ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: williamr@4: @return ETrue if automatic resource management is enabled; EFalse williamr@4: otherwise. williamr@4: */ williamr@4: using LAutoRefBase::IsEnabled; williamr@4: williamr@4: /** williamr@4: Returns a reference to the managed object of type T. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::Get; williamr@4: williamr@4: /** williamr@4: Overloaded indirection operator function. williamr@4: williamr@4: @return A reference to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::operator*; williamr@4: williamr@4: /** williamr@4: Overloaded class member access operator function. williamr@4: williamr@4: @return A pointer to the managed object of type T. williamr@4: */ williamr@4: using LAutoRefBase::operator->; williamr@4: williamr@4: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: LCleanedupRef* cleanupRef = static_cast(aPtr); williamr@4: williamr@4: if (cleanupRef->IsEnabled()) williamr@4: { williamr@4: CleanupStrategy::Cleanup(cleanupRef->iPtr); williamr@4: } williamr@4: } williamr@4: williamr@4: using LAutoRefBase::Disable; williamr@4: williamr@4: void Swap(LCleanedupRef& aRef) williamr@4: { williamr@4: LAutoRefBase::Swap(aRef); williamr@4: } williamr@4: williamr@4: private: williamr@4: using LAutoRefBase::iPtr; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class that provides automatic cleanup using a TCleanupOperation williamr@4: on the destruction of the LManagedGuard object. williamr@4: williamr@4: @note This class can only be used to define object scoped cleanup williamr@4: to guard object destruction, never local stack scoped cleanup. See williamr@4: below for an explanation and links to management classes suitable williamr@4: for use in different contexts. williamr@4: williamr@4: This class can be used to manage a TCleanupOperation in such a way williamr@4: that the specified cleanup operation is guaranteed to be called williamr@4: when the guarding object is destroyed; typically when the object williamr@4: containing it is deleted. williamr@4: williamr@4: The constructors of this class never leave, so data members defined with williamr@4: this type may be initialized safely during any phase of williamr@4: construction of the owning class. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Dismiss(), while cleanup may be forced at any time by calling williamr@4: Execute(). williamr@4: williamr@4: @code williamr@4: class CComposite : public CBase williamr@4: { williamr@4: public: williamr@4: CONSTRUCTORS_MAY_LEAVE williamr@4: williamr@4: CComposite(RCleanable* aObj) williamr@4: : iObj(RCleanable::Cleanup, aObj) williamr@4: { williamr@4: } williamr@4: williamr@4: ~CComposite() williamr@4: { williamr@4: // RCleanable::Cleanup(iObj) is automatically invoked williamr@4: } williamr@4: williamr@4: private: williamr@4: LManagedGuard iObj; williamr@4: }; williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template simply relies on reliable williamr@4: execution of its destructor. If used for a local variable rather williamr@4: than a data member, cleanup will occur but out-of-order compared to williamr@4: objects protected using the LCleanupXxx variants or the williamr@4: CleanupStack directly. Therefore it is not recommended for use in williamr@4: that context. williamr@4: williamr@4: These management classes may be used as the basis for implementing williamr@4: leave-safe single-phase construction, since fully initialized williamr@4: data members protected in this way will get destroyed (so reliably williamr@4: triggering cleanup) if their containing classes leave during williamr@4: execution of their constructors. Note, however, that single-phase williamr@4: construction must be explicitly enabled in the containing class williamr@4: using the CONSTRUCTORS_MAY_LEAVE macro. williamr@4: williamr@4: @see LCleanedupGuard which has the same interface, but uses the cleanup williamr@4: stack and is suitable for use as a local to guard local scope exit williamr@4: @see CONSTRUCTORS_MAY_LEAVE williamr@4: */ williamr@4: class LManagedGuard williamr@4: { williamr@4: public: williamr@4: /** williamr@4: Constructor. Creates a LCleanedupGuard object that, when enabled, williamr@4: automatically invokes upon destruction a cleanup operation williamr@4: specified by the aCleanupOperation parameter with the pointer to williamr@4: data specified by the aData parameter. williamr@4: williamr@4: @param aCleanupOperation A cleanup operation. williamr@4: @param aData Pointer to data to be passed to the cleanup operation williamr@4: */ williamr@4: LManagedGuard(TCleanupOperation aCleanupOperation, TAny* aData = 0) williamr@4: : iCleanupOperation(aCleanupOperation), williamr@4: iData(aData) williamr@4: { williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. williamr@4: */ williamr@4: ~LManagedGuard() williamr@4: { williamr@4: Execute(); williamr@4: } williamr@4: williamr@4: /** williamr@4: Executes the guard cleanup operation. williamr@4: */ williamr@4: void Execute() williamr@4: { williamr@4: if (iCleanupOperation) williamr@4: { williamr@4: iCleanupOperation(iData); williamr@4: } williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the guard. williamr@4: */ williamr@4: void Dismiss() williamr@4: { williamr@4: iCleanupOperation = NULL; williamr@4: } williamr@4: williamr@4: private: williamr@4: LManagedGuard(const LManagedGuard&); williamr@4: LManagedGuard& operator=(const LManagedGuard&); williamr@4: williamr@4: TCleanupOperation iCleanupOperation; williamr@4: TAny* iData; williamr@4: }; williamr@4: williamr@4: williamr@4: /** williamr@4: A class that provides CleanupStack-based local-scope automatic williamr@4: cleanup using a TCleanupOperation on the destruction of the williamr@4: LManagedGuard object. williamr@4: williamr@4: @note This class can only be used to define a local stack scoped williamr@4: cleanup, never an object scoped cleanup to guard object williamr@4: destruction. See below for an explanation and links to management williamr@4: classes suitable for use in different contexts. williamr@4: williamr@4: This class can be used to manage a TCleanupOperation in such a way williamr@4: that the specified cleanup operation is guaranteed to be called williamr@4: when either of the following occur: williamr@4: williamr@4: - The guarding local variable goes out of scope normally williamr@4: - The guarding local variable goes out of scope due to an williamr@4: untrapped leave causing the scope to be exited non-locally williamr@4: williamr@4: The constructors of this class may leave. williamr@4: williamr@4: Automatic cleanup may be disabled at any time by calling williamr@4: Dismiss(), while cleanup may be forced at any time by calling williamr@4: Execute(). williamr@4: williamr@4: @code williamr@4: // block scope example williamr@4: { williamr@4: RCleanable obj; williamr@4: LCleanedupGuard cleanGuard(RCleanable::Cleanup, &obj); williamr@4: williamr@4: obj.DoSomethingL(); // leave-safe williamr@4: if (Finished()) williamr@4: return; // RCleanable::Cleanup is invoked automatically when exiting from scope williamr@4: obj.DoSomethingElseL(); // leave-safe williamr@4: // RCleanable::Cleanup is invoked automatically when exiting from scope williamr@4: } williamr@4: @endcode williamr@4: williamr@4: Behind the scenes, this class template is implemented in terms of williamr@4: the thread-local CleanupStack, restricting its use to local stack williamr@4: scope. This use of the CleanupStack ensures a consistent cleanup williamr@4: order between functions that call one another, even if they use williamr@4: different cleanup idioms. williamr@4: williamr@4: @see LManagedGuard which has the same interface, but does not use the cleanup williamr@4: stack and is suitable for use as the data member of a class to guard williamr@4: object destruction. williamr@4: */ williamr@4: class LCleanedupGuard williamr@4: { williamr@4: public: williamr@4: /** williamr@4: Constructor. Creates a LCleanedupGuard object that, when enabled, williamr@4: automatically invokes upon destruction a cleanup operation williamr@4: specified by the aCleanupOperation parameter with the pointer to williamr@4: data specified by the aData parameter. williamr@4: williamr@4: @param aCleanupOperation A cleanup operation. williamr@4: @param aData Pointer to data to be passed to the cleanup operation williamr@4: */ williamr@4: LCleanedupGuard(TCleanupOperation aCleanupOperation, TAny* aData = 0) williamr@4: : iCleanupOperation(aCleanupOperation), williamr@4: iData(aData) williamr@4: { williamr@4: CleanupStack::PushL(TCleanupItem(Cleanup, this)); williamr@4: } williamr@4: williamr@4: /** williamr@4: Destructor. williamr@4: */ williamr@4: ~LCleanedupGuard() williamr@4: { williamr@4: ManagedPopCleanupStackItem(iCleanupOperation); williamr@4: } williamr@4: williamr@4: /** williamr@4: Executes the guard cleanup operation. williamr@4: */ williamr@4: void Execute() williamr@4: { williamr@4: if (iCleanupOperation) williamr@4: { williamr@4: iCleanupOperation(iData); williamr@4: } williamr@4: } williamr@4: williamr@4: /** williamr@4: Disables the guard. williamr@4: */ williamr@4: void Dismiss() williamr@4: { williamr@4: iCleanupOperation = NULL; williamr@4: } williamr@4: williamr@4: static void Cleanup(TAny* aPtr) williamr@4: { williamr@4: LCleanedupGuard* guard = static_cast(aPtr); williamr@4: guard->Execute(); williamr@4: } williamr@4: williamr@4: private: williamr@4: LCleanedupGuard(const LCleanedupGuard&); williamr@4: LCleanedupGuard& operator=(const LCleanedupGuard&); williamr@4: williamr@4: williamr@4: TCleanupOperation iCleanupOperation; williamr@4: TAny* iData; williamr@4: }; williamr@4: williamr@4: #endif // !EMANAGED_H williamr@4: