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