sl@0: // Copyright (c) 1995-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 the License "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: // e32\euser\cbase\ub_cln.cpp sl@0: // sl@0: // sl@0: sl@0: #include "ub_std.h" sl@0: #include "us_data.h" sl@0: sl@0: const TInt KCleanupGranularity=4; sl@0: const TInt KCleanupInitialSlots=8; sl@0: sl@0: LOCAL_C void doDelete(CBase *aPtr) sl@0: // sl@0: // Delete the CBase pointer sl@0: // sl@0: { sl@0: sl@0: delete aPtr; sl@0: } sl@0: sl@0: LOCAL_C CCleanup &cleanup() sl@0: // sl@0: // Return the CTrapHandler's cleanup list. sl@0: // sl@0: { sl@0: sl@0: TCleanupTrapHandler *pH=(TCleanupTrapHandler *)GetTrapHandler(); sl@0: __ASSERT_ALWAYS(pH!=NULL,Panic(EClnNoTrapHandlerInstalled)); sl@0: return(pH->Cleanup()); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: TCleanupTrapHandler::TCleanupTrapHandler() sl@0: : iCleanup(NULL) sl@0: /** sl@0: Default constructor. sl@0: */ sl@0: {} sl@0: sl@0: sl@0: sl@0: sl@0: void TCleanupTrapHandler::Trap() sl@0: /** sl@0: Deals with the invocation of a call to TRAP. sl@0: */ sl@0: { sl@0: sl@0: iCleanup->NextLevel(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void TCleanupTrapHandler::UnTrap() sl@0: /** sl@0: Deals with a function exiting a TRAP without leaving. sl@0: */ sl@0: { sl@0: sl@0: iCleanup->PreviousLevel(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void TCleanupTrapHandler::Leave(TInt /*aValue*/) sl@0: /** sl@0: Deals with a function within a TRAP leaving. sl@0: sl@0: @param aValue The leave value. sl@0: */ sl@0: { sl@0: sl@0: iCleanup->PopAndDestroyAll(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: class TCleanupStackItem sl@0: { sl@0: public: sl@0: void Set(const TCleanupItem &aItem); sl@0: inline void Cleanup(); sl@0: inline TBool IsLevelMarker() const; sl@0: inline void MarkLevel(); sl@0: inline void PushLevel(); sl@0: inline TInt PopLevel(); sl@0: inline TBool Check(TAny* aExpectedItem) const; sl@0: private: sl@0: TCleanupOperation iOperation; sl@0: union sl@0: { sl@0: TAny *iPtr; sl@0: TInt iLevelCount; // may stack >1 level on this entry sl@0: }; sl@0: }; sl@0: inline void TCleanupStackItem::MarkLevel() sl@0: { iOperation=NULL; iLevelCount=1; } sl@0: inline TBool TCleanupStackItem::IsLevelMarker() const sl@0: { return (iOperation==NULL); } sl@0: inline void TCleanupStackItem::Cleanup() sl@0: { (*iOperation)(iPtr); } sl@0: inline void TCleanupStackItem::PushLevel() sl@0: { ++iLevelCount; } sl@0: inline TInt TCleanupStackItem::PopLevel() sl@0: { return (--iLevelCount); } sl@0: inline TBool TCleanupStackItem::Check(TAny* aExpectedItem) const sl@0: { return (iOperation && iPtr==aExpectedItem); } sl@0: sl@0: void TCleanupStackItem::Set(const TCleanupItem &anItem) sl@0: // sl@0: // Initialise an entry as a cleanup item. sl@0: // sl@0: { sl@0: sl@0: __ASSERT_ALWAYS(anItem.iOperation!=NULL,Panic(EClnNoCleanupOperation)); sl@0: iOperation=anItem.iOperation; sl@0: iPtr=anItem.iPtr; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CCleanup *CCleanup::New() sl@0: /** sl@0: Creates a new cleanup stack object. sl@0: sl@0: The cleanup stack itself is allocated with enough space initially to hold sl@0: a number of stack items. sl@0: sl@0: @return A pointer to the new cleanup stack object. This is Null if there is sl@0: insufficient memory. sl@0: */ sl@0: { sl@0: sl@0: CCleanup *pC=new CCleanup; sl@0: if (pC!=NULL) sl@0: { sl@0: TCleanupStackItem *base=(TCleanupStackItem *)User::Alloc(KCleanupInitialSlots*sizeof(TCleanupStackItem)); sl@0: if (base!=NULL) sl@0: { sl@0: pC->iBase=base; sl@0: pC->iNext=base; sl@0: pC->iTop=base+KCleanupInitialSlots; sl@0: } sl@0: else sl@0: { sl@0: delete pC; sl@0: pC=NULL; sl@0: } sl@0: } sl@0: return(pC); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CCleanup *CCleanup::NewL() sl@0: /** sl@0: Creates a new cleanup stack object, and leaves if there is insufficient memory sl@0: to create it. sl@0: sl@0: The cleanup stack itself is allocated with enough space initially to hold sl@0: a number of stack items. sl@0: sl@0: @return A pointer to the new cleanup stack object. This is Null if there is sl@0: nsufficient memory. sl@0: */ sl@0: { sl@0: sl@0: CCleanup *pC=New(); sl@0: User::LeaveIfNull(pC); sl@0: return(pC); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CCleanup::CCleanup() sl@0: /** sl@0: Default constructor. sl@0: */ sl@0: { sl@0: sl@0: // iBase=NULL; sl@0: // iTop=NULL; sl@0: // iNext=NULL; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CCleanup::~CCleanup() sl@0: /** sl@0: Destructor. sl@0: sl@0: Pops and destroys all items from the cleanup stack and then destroys sl@0: the cleanup stack itself. sl@0: */ sl@0: { sl@0: sl@0: while (iNext>iBase) sl@0: PopAndDestroyAll(); sl@0: User::Free(iBase); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::NextLevel() sl@0: /** sl@0: Goes to the next cleanup level. sl@0: */ sl@0: { sl@0: sl@0: if (iNext>iBase && (iNext-1)->IsLevelMarker()) sl@0: (iNext-1)->PushLevel(); sl@0: else sl@0: { sl@0: iNext->MarkLevel(); sl@0: ++iNext; sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PreviousLevel() sl@0: /** sl@0: Goes to the previous cleanup level. sl@0: sl@0: @panic E32USER-CBase 71 If the previous stack item does not represent a cleanup sl@0: level. sl@0: */ sl@0: { sl@0: sl@0: TCleanupStackItem *item=iNext; sl@0: --item; sl@0: // current level must be empty sl@0: __ASSERT_ALWAYS(item->IsLevelMarker(), Panic(EClnLevelNotEmpty)); sl@0: if (item->PopLevel()) sl@0: ++item; sl@0: iNext=item; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PushL(TAny *aPtr) sl@0: /** sl@0: Pushes a cleanup item onto the cleanup stack. sl@0: sl@0: The cleanup item represents an operation that frees the specified heap cell. sl@0: sl@0: @param aPtr A pointer to a heap cell that will be freed by sl@0: the cleanup operation. sl@0: */ sl@0: { sl@0: sl@0: PushL(TCleanupItem(User::Free,aPtr)); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PushL(CBase *anObject) sl@0: /** sl@0: Pushes a cleanup item onto the cleanup stack. sl@0: sl@0: The cleanup item represents an operation that deletes the specified CBase sl@0: derived object. sl@0: sl@0: @param anObject A pointer to CBase derived object that will be deleted by sl@0: the cleanup operation. sl@0: */ sl@0: { sl@0: sl@0: PushL(TCleanupItem(TCleanupOperation(doDelete),anObject)); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PushL(TCleanupItem anItem) sl@0: /** sl@0: Pushes a cleanup item onto the cleanup stack. sl@0: sl@0: The cleanup item represents a call back operation that performs the required sl@0: cleanup. sl@0: sl@0: @param anItem Encapsulates a cleanup operation and an object on which the sl@0: cleanup operation is to be performed. sl@0: sl@0: @see CleanupClosePushL sl@0: @see CleanupReleasePushL sl@0: @see CleanupDeletePushL sl@0: */ sl@0: { sl@0: sl@0: TCleanupStackItem *item=iNext; sl@0: __ASSERT_ALWAYS(item>iBase,Panic(EClnPushAtLevelZero)); sl@0: __ASSERT_ALWAYS(itemSet(anItem); sl@0: iNext=++item; sl@0: // sl@0: // We always try and make sure that there are two free slots in the cleanup array. sl@0: // one for a level marker and one for an item to follow it sl@0: // If this fails its o.k. as we have already added the entry to the list, so sl@0: // it will be cleaned up o.k. sl@0: // sl@0: if (item+1>=iTop) sl@0: { sl@0: TInt size=(TUint8 *)(iTop+KCleanupGranularity)-(TUint8 *)iBase; sl@0: TCleanupStackItem *base=(TCleanupStackItem *)User::ReAllocL(iBase,size); sl@0: iNext=PtrAdd(base,(TUint8 *)item-(TUint8 *)iBase); sl@0: iBase=base; sl@0: iTop=PtrAdd(base,size); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::DoPop(TInt aCount,TBool aDestroy) sl@0: /** sl@0: Provides an implementation for Pop() and PopAndDestroy(). sl@0: sl@0: @param aCount The number of cleanup items to be popped from sl@0: the cleanup stack. sl@0: @param aDestroy ETrue, if cleanup is to be performed; EFalse, otherwise. sl@0: */ sl@0: { sl@0: sl@0: __ASSERT_ALWAYS(aCount>=0,Panic(EClnPopCountNegative)); sl@0: __ASSERT_ALWAYS((iNext-aCount)>=iBase,Panic(EClnPopUnderflow)); sl@0: while (aCount--) sl@0: { sl@0: --iNext; sl@0: __ASSERT_ALWAYS(!iNext->IsLevelMarker(),Panic(EClnPopAcrossLevels)); sl@0: if (aDestroy) sl@0: { sl@0: TInt offset = iNext - iBase; sl@0: iNext->Cleanup(); sl@0: // Check that there are no extra items on the cleanup stack sl@0: // (if there are, we will not be deleting the right aCount items) sl@0: __ASSERT_ALWAYS((iNext - iBase) == offset,Panic(EClnStackModified)); sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::DoPopAll(TBool aDestroy) sl@0: /** sl@0: Provides an implementation for PopAll() and PopAndDestroyAll(). sl@0: sl@0: @param aDestroy ETrue, if cleanup is to be performed; EFalse, otherwise. sl@0: */ sl@0: { sl@0: sl@0: __ASSERT_ALWAYS(iNext>iBase,Panic(EClnLevelUnderflow)); sl@0: while (!(--iNext)->IsLevelMarker()) sl@0: { sl@0: if (aDestroy) sl@0: iNext->Cleanup(); sl@0: } sl@0: if (iNext->PopLevel()) sl@0: ++iNext; // still marks a level sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::Pop() sl@0: /** sl@0: Pops a single cleanup item from the cleanup stack. sl@0: sl@0: @panic E32USER-CBase 64 If there are no items on the cleanup stack. sl@0: @panic E32USER-CBase 63 If a cleanup level is crossed. sl@0: */ sl@0: { sl@0: sl@0: DoPop(1,EFalse); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::Pop(TInt aCount) sl@0: /** sl@0: Pops the specified number of cleanup items from the cleanup stack. sl@0: sl@0: @param aCount The number of cleanup items to be popped from the cleanup stack. sl@0: sl@0: @panic E32USER-CBase 70 If the specified number of cleanup items is negative. sl@0: @panic E32USER-CBase 64 If the specifed number of items is greater than the sl@0: number of items on the cleanup stack. sl@0: @panic E32USER-CBase 63 If the specified number of items is such that it causes sl@0: a cleanup level to be crossed. sl@0: */ sl@0: { sl@0: sl@0: DoPop(aCount,EFalse); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PopAll() sl@0: /** sl@0: Pops all cleanup items at the current level, and then decrements the level. sl@0: */ sl@0: { sl@0: sl@0: DoPopAll(EFalse); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PopAndDestroy() sl@0: /** sl@0: Pops a single cleanup item from the cleanup stack, and invokes its cleanup sl@0: operation. sl@0: sl@0: @panic E32USER-CBase 64 If there are no items on the cleanup stack. sl@0: @panic E32USER-CBase 63 If a cleanup level is crossed. sl@0: */ sl@0: { sl@0: sl@0: DoPop(1,ETrue); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PopAndDestroy(TInt aCount) sl@0: /** sl@0: Pops the specified number of cleanup items from the cleanup stack, and invokes sl@0: their cleanup operations. sl@0: sl@0: @param aCount The number of cleanup items to be popped from the cleanup stack. sl@0: sl@0: @panic E32USER-CBase 70 If the specified number of cleanup items is negative. sl@0: @panic E32USER-CBase 64 If the specifed number of items is greater than the sl@0: number of items on the cleanup stack. sl@0: @panic E32USER-CBase 63 If the specified number of items is such that it causes sl@0: a cleanup level to be crossed. sl@0: */ sl@0: { sl@0: sl@0: DoPop(aCount,ETrue); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::PopAndDestroyAll() sl@0: /** sl@0: Pops all cleanup items at the current level, invokes their cleanup operations sl@0: and then decrements the level. sl@0: */ sl@0: { sl@0: sl@0: DoPopAll(ETrue); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CCleanup::Check(TAny* aExpectedItem) sl@0: /** sl@0: Checks that the cleanup item at the top of the cleanup stack sl@0: represents a cleanup operation for the specified object. sl@0: sl@0: @param aExpectedItem The object which is the subject of the test. sl@0: */ sl@0: { sl@0: sl@0: TCleanupStackItem* last=iNext-1; sl@0: __ASSERT_ALWAYS(last>=iBase && last->Check(aExpectedItem), Panic(EClnCheckFailed)); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CTrapCleanup *CTrapCleanup::New() sl@0: /** sl@0: Allocates and constructs a cleanup stack. sl@0: sl@0: If successfully constructed, this cleanup stack becomes sl@0: the current cleanup stack. sl@0: sl@0: @return A pointer to the new cleanup stack. This pointer is NULL, if allocation sl@0: fails. sl@0: */ sl@0: { sl@0: sl@0: CTrapCleanup *pT=new CTrapCleanup; sl@0: if (pT!=NULL) sl@0: { sl@0: CCleanup *pC=CCleanup::New(); sl@0: if (pC!=NULL) sl@0: { sl@0: pT->iHandler.iCleanup=pC; sl@0: pT->iOldHandler=User::SetTrapHandler(&pT->iHandler); sl@0: } sl@0: else sl@0: { sl@0: delete pT; sl@0: pT=NULL; sl@0: } sl@0: } sl@0: return(pT); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CTrapCleanup::CTrapCleanup() sl@0: /** sl@0: Default constructor. sl@0: */ sl@0: // : iHandler() sl@0: { sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CTrapCleanup::~CTrapCleanup() sl@0: /** sl@0: Destructor. sl@0: sl@0: Frees resources owned by the object, prior to its destruction. This cleanup sl@0: stack ceases to be the current cleanup stack. sl@0: sl@0: If there is a stack of cleanup stacks, then the next cleanup stack becomes sl@0: the current cleanup stack. sl@0: */ sl@0: { sl@0: sl@0: if (iHandler.iCleanup!=NULL) sl@0: { sl@0: User::SetTrapHandler(iOldHandler); sl@0: delete iHandler.iCleanup; sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::PushL(TAny *aPtr) sl@0: /** sl@0: Pushes a pointer to an object onto the cleanup stack. sl@0: sl@0: If a leave occurs while an object is on the stack, it is cleaned sl@0: up automatically. Untyped objects are cleaned up with User::Free() sl@0: (a rather limited form of cleanup, not even the C++ destructor is called). sl@0: sl@0: Typically, when an object has been fully constructed and it can be guaranteed sl@0: that a pointer to this new object is stored in some other object before a leave sl@0: occurs, issue CleanupStack::Pop() to pop it back off the stack. sl@0: sl@0: If no cleanup stack has been allocated, a panic occurs. sl@0: sl@0: It is guaranteed that the object is pushed onto the cleanup stack. However, sl@0: this function may leave if a stack frame for the next PushL() cannot be sl@0: allocated. In this case, the cleanup stack will be cleaned up as normal, and sl@0: no extra programmer intervention is needed. sl@0: sl@0: @param aPtr Pointer to any object. If cleanup is necessary, the object will be sl@0: freed by User::Free(), which does not invoke any destructor: it sl@0: simply frees its memory sl@0: sl@0: @panic E32USER-CBase 66 if a call to this function is made when no prior sl@0: call to TRAP has been made. sl@0: */ sl@0: { sl@0: sl@0: cleanup().PushL(aPtr); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::PushL(CBase *aPtr) sl@0: /** sl@0: Pushes a pointer to an object onto the cleanup stack. sl@0: sl@0: If a leave occurs while an object is on the stack, it is cleaned sl@0: up automatically. CBase derived objects are cleaned up with delete. sl@0: sl@0: Typically, when an object has been fully constructed and it can be guaranteed sl@0: that a pointer to this new object is stored in some other object before a leave sl@0: occurs, issue CleanupStack::Pop() to pop it back off the stack. sl@0: sl@0: If no cleanup stack has been allocated, a panic occurs. sl@0: sl@0: It is guaranteed that the object is pushed onto the cleanup stack. However, sl@0: this function may leave if a stack frame for the next PushL() cannot be sl@0: allocated. In this case, the cleanup stack will be cleaned up as normal, sl@0: and no extra programmer intervention is needed. sl@0: sl@0: @param aPtr Pointer to a CBase-derived object. If cleanup is necessary, the sl@0: object will be freed by delete, thus invoking its destructor, sl@0: and freeing its memory. sl@0: sl@0: @panic E32USER-CBase 66 if a call to this function is made when no prior sl@0: call to TRAP has been made. sl@0: */ sl@0: { sl@0: sl@0: cleanup().PushL(aPtr); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::PushL(TCleanupItem anItem) sl@0: /** sl@0: Pushes a cleanup item onto the cleanup stack. sl@0: sl@0: If a leave occurs while a cleanup item is on the stack, the cleanup operation sl@0: defined in the construction of the TCleanupItem, is invoked. sl@0: sl@0: Typically, when an object has been fully constructed and it can be guaranteed sl@0: that a pointer to this new object is stored in some other object before a leave sl@0: occurs, issue CleanupStack::Pop() to pop it back off the stack. sl@0: sl@0: If no cleanup stack has been allocated, a panic occurs. sl@0: sl@0: It is guaranteed that the object is pushed onto the cleanup stack. However, sl@0: this function may leave if a stack frame for the next PushL() cannot be sl@0: allocated. In this case, the cleanup stack will be cleaned up as normal, sl@0: and no extra programmer intervention is needed. sl@0: sl@0: @param anItem A cleanup item. If cleanup is necessary, the cleanup operation sl@0: defined in the construction of anItem is called. sl@0: sl@0: @panic E32USER-CBase 66 if a call to this function is made when no prior sl@0: call to TRAP has been made. sl@0: */ sl@0: { sl@0: sl@0: cleanup().PushL(anItem); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::Pop() sl@0: /** sl@0: Pops an object previously pushed onto the cleanup stack sl@0: by CleanupStack::PushL(). sl@0: sl@0: After an object has been successfully constructed and stored within sl@0: another object, it cannot be orphaned and, therefore, the object sl@0: (i.e. a pointer or a cleanup item) can be popped from the cleanup stack. sl@0: sl@0: If no cleanup stack has been allocated, or there is nothing on the stack, sl@0: a panic is raised. sl@0: */ sl@0: { sl@0: sl@0: cleanup().Pop(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::Pop(TInt aCount) sl@0: /** sl@0: Pops a specified number of objects previously pushed onto the sl@0: cleanup stack by CleanupStack::PushL(). sl@0: sl@0: After an object has been successfully constructed and stored within another sl@0: object, it cannot be orphaned and, therefore, the object(s), that is, pointers sl@0: and cleanup items can be popped from the cleanup stack. sl@0: sl@0: If no cleanup stack has been allocated, or there is nothing on the stack, sl@0: a panic is raised. sl@0: sl@0: @param aCount The number of objects to be popped off the cleanup stack. sl@0: */ sl@0: { sl@0: sl@0: cleanup().Pop(aCount); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::PopAndDestroy() sl@0: /** sl@0: Pops and cleans up an item pushed onto the stack. sl@0: sl@0: If the item on the stack is a CBase* pointer, the pointer is removed from sl@0: the stack and the object is destroyed with delete. sl@0: sl@0: If the item on the stack is a TAny* pointer, the pointer is removed from sl@0: the stack and the memory occupied by the object is freed with User::Free(). sl@0: sl@0: If the item on the stack is a cleanup item, i.e. an object of sl@0: type TCleanupItem, the item is removed from the stack and the cleanup sl@0: operation defined during construction of the TCleanupItem object is invoked. sl@0: sl@0: If no cleanup stack has been allocated, or there is nothing on the stack, sl@0: a panic occurs. sl@0: */ sl@0: { sl@0: sl@0: cleanup().PopAndDestroy(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::PopAndDestroy(TInt aCount) sl@0: /** sl@0: Pops and cleans up the specified number of items pushed onto the stack. sl@0: sl@0: If an item on the stack is a CBase* pointer, the pointer is removed from sl@0: the stack and the object is destroyed with delete. sl@0: sl@0: If an item on the stack is a TAny* pointer, the pointer is removed from the sl@0: stack and the memory occupied by the object is freed with User::Free(). sl@0: sl@0: If an item on the stack is a cleanup item, i.e. an object of type TCleanupItem, sl@0: the item is removed from the stack and the cleanup operation defined during sl@0: construction of the TCleanupItem object is invoked. sl@0: sl@0: If no cleanup stack has been allocated, or there is nothing on the stack, sl@0: a panic occurs. sl@0: sl@0: @param aCount The number of objects to be popped off the cleanup stack and sl@0: destroyed. sl@0: */ sl@0: { sl@0: sl@0: cleanup().PopAndDestroy(aCount); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CleanupStack::Check(TAny* aExpectedItem) sl@0: /** sl@0: Checks that the specified object is at the top of the cleanup stack. sl@0: sl@0: If the specified item is not at the top of the cleanup stack, then the function sl@0: raises an E32USER-CBase 90 panic. sl@0: sl@0: The function is part of Symbian OS in both debug and release builds, and is sl@0: an aid to debugging. sl@0: sl@0: @param aExpectedItem A pointer to the item expected to be at the top of the sl@0: cleanup stack. sl@0: */ sl@0: { sl@0: sl@0: cleanup().Check(aExpectedItem); sl@0: }