First public contribution.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\cbase\ub_cln.cpp
21 const TInt KCleanupGranularity=4;
22 const TInt KCleanupInitialSlots=8;
24 LOCAL_C void doDelete(CBase *aPtr)
26 // Delete the CBase pointer
33 LOCAL_C CCleanup &cleanup()
35 // Return the CTrapHandler's cleanup list.
39 TCleanupTrapHandler *pH=(TCleanupTrapHandler *)GetTrapHandler();
40 __ASSERT_ALWAYS(pH!=NULL,Panic(EClnNoTrapHandlerInstalled));
41 return(pH->Cleanup());
47 TCleanupTrapHandler::TCleanupTrapHandler()
57 void TCleanupTrapHandler::Trap()
59 Deals with the invocation of a call to TRAP.
63 iCleanup->NextLevel();
69 void TCleanupTrapHandler::UnTrap()
71 Deals with a function exiting a TRAP without leaving.
75 iCleanup->PreviousLevel();
81 void TCleanupTrapHandler::Leave(TInt /*aValue*/)
83 Deals with a function within a TRAP leaving.
85 @param aValue The leave value.
89 iCleanup->PopAndDestroyAll();
95 class TCleanupStackItem
98 void Set(const TCleanupItem &aItem);
99 inline void Cleanup();
100 inline TBool IsLevelMarker() const;
101 inline void MarkLevel();
102 inline void PushLevel();
103 inline TInt PopLevel();
104 inline TBool Check(TAny* aExpectedItem) const;
106 TCleanupOperation iOperation;
110 TInt iLevelCount; // may stack >1 level on this entry
113 inline void TCleanupStackItem::MarkLevel()
114 { iOperation=NULL; iLevelCount=1; }
115 inline TBool TCleanupStackItem::IsLevelMarker() const
116 { return (iOperation==NULL); }
117 inline void TCleanupStackItem::Cleanup()
118 { (*iOperation)(iPtr); }
119 inline void TCleanupStackItem::PushLevel()
121 inline TInt TCleanupStackItem::PopLevel()
122 { return (--iLevelCount); }
123 inline TBool TCleanupStackItem::Check(TAny* aExpectedItem) const
124 { return (iOperation && iPtr==aExpectedItem); }
126 void TCleanupStackItem::Set(const TCleanupItem &anItem)
128 // Initialise an entry as a cleanup item.
132 __ASSERT_ALWAYS(anItem.iOperation!=NULL,Panic(EClnNoCleanupOperation));
133 iOperation=anItem.iOperation;
140 EXPORT_C CCleanup *CCleanup::New()
142 Creates a new cleanup stack object.
144 The cleanup stack itself is allocated with enough space initially to hold
145 a number of stack items.
147 @return A pointer to the new cleanup stack object. This is Null if there is
152 CCleanup *pC=new CCleanup;
155 TCleanupStackItem *base=(TCleanupStackItem *)User::Alloc(KCleanupInitialSlots*sizeof(TCleanupStackItem));
160 pC->iTop=base+KCleanupInitialSlots;
174 EXPORT_C CCleanup *CCleanup::NewL()
176 Creates a new cleanup stack object, and leaves if there is insufficient memory
179 The cleanup stack itself is allocated with enough space initially to hold
180 a number of stack items.
182 @return A pointer to the new cleanup stack object. This is Null if there is
188 User::LeaveIfNull(pC);
195 EXPORT_C CCleanup::CCleanup()
209 EXPORT_C CCleanup::~CCleanup()
213 Pops and destroys all items from the cleanup stack and then destroys
214 the cleanup stack itself.
226 EXPORT_C void CCleanup::NextLevel()
228 Goes to the next cleanup level.
232 if (iNext>iBase && (iNext-1)->IsLevelMarker())
233 (iNext-1)->PushLevel();
244 EXPORT_C void CCleanup::PreviousLevel()
246 Goes to the previous cleanup level.
248 @panic E32USER-CBase 71 If the previous stack item does not represent a cleanup
253 TCleanupStackItem *item=iNext;
255 // current level must be empty
256 __ASSERT_ALWAYS(item->IsLevelMarker(), Panic(EClnLevelNotEmpty));
257 if (item->PopLevel())
265 EXPORT_C void CCleanup::PushL(TAny *aPtr)
267 Pushes a cleanup item onto the cleanup stack.
269 The cleanup item represents an operation that frees the specified heap cell.
271 @param aPtr A pointer to a heap cell that will be freed by
272 the cleanup operation.
276 PushL(TCleanupItem(User::Free,aPtr));
282 EXPORT_C void CCleanup::PushL(CBase *anObject)
284 Pushes a cleanup item onto the cleanup stack.
286 The cleanup item represents an operation that deletes the specified CBase
289 @param anObject A pointer to CBase derived object that will be deleted by
290 the cleanup operation.
294 PushL(TCleanupItem(TCleanupOperation(doDelete),anObject));
300 EXPORT_C void CCleanup::PushL(TCleanupItem anItem)
302 Pushes a cleanup item onto the cleanup stack.
304 The cleanup item represents a call back operation that performs the required
307 @param anItem Encapsulates a cleanup operation and an object on which the
308 cleanup operation is to be performed.
310 @see CleanupClosePushL
311 @see CleanupReleasePushL
312 @see CleanupDeletePushL
316 TCleanupStackItem *item=iNext;
317 __ASSERT_ALWAYS(item>iBase,Panic(EClnPushAtLevelZero));
318 __ASSERT_ALWAYS(item<iTop,Panic(EClnNoFreeSlotItem));
322 // We always try and make sure that there are two free slots in the cleanup array.
323 // one for a level marker and one for an item to follow it
324 // If this fails its o.k. as we have already added the entry to the list, so
325 // it will be cleaned up o.k.
329 TInt size=(TUint8 *)(iTop+KCleanupGranularity)-(TUint8 *)iBase;
330 TCleanupStackItem *base=(TCleanupStackItem *)User::ReAllocL(iBase,size);
331 iNext=PtrAdd(base,(TUint8 *)item-(TUint8 *)iBase);
333 iTop=PtrAdd(base,size);
340 EXPORT_C void CCleanup::DoPop(TInt aCount,TBool aDestroy)
342 Provides an implementation for Pop() and PopAndDestroy().
344 @param aCount The number of cleanup items to be popped from
346 @param aDestroy ETrue, if cleanup is to be performed; EFalse, otherwise.
350 __ASSERT_ALWAYS(aCount>=0,Panic(EClnPopCountNegative));
351 __ASSERT_ALWAYS((iNext-aCount)>=iBase,Panic(EClnPopUnderflow));
355 __ASSERT_ALWAYS(!iNext->IsLevelMarker(),Panic(EClnPopAcrossLevels));
358 TInt offset = iNext - iBase;
360 // Check that there are no extra items on the cleanup stack
361 // (if there are, we will not be deleting the right aCount items)
362 __ASSERT_ALWAYS((iNext - iBase) == offset,Panic(EClnStackModified));
370 EXPORT_C void CCleanup::DoPopAll(TBool aDestroy)
372 Provides an implementation for PopAll() and PopAndDestroyAll().
374 @param aDestroy ETrue, if cleanup is to be performed; EFalse, otherwise.
378 __ASSERT_ALWAYS(iNext>iBase,Panic(EClnLevelUnderflow));
379 while (!(--iNext)->IsLevelMarker())
384 if (iNext->PopLevel())
385 ++iNext; // still marks a level
391 EXPORT_C void CCleanup::Pop()
393 Pops a single cleanup item from the cleanup stack.
395 @panic E32USER-CBase 64 If there are no items on the cleanup stack.
396 @panic E32USER-CBase 63 If a cleanup level is crossed.
406 EXPORT_C void CCleanup::Pop(TInt aCount)
408 Pops the specified number of cleanup items from the cleanup stack.
410 @param aCount The number of cleanup items to be popped from the cleanup stack.
412 @panic E32USER-CBase 70 If the specified number of cleanup items is negative.
413 @panic E32USER-CBase 64 If the specifed number of items is greater than the
414 number of items on the cleanup stack.
415 @panic E32USER-CBase 63 If the specified number of items is such that it causes
416 a cleanup level to be crossed.
420 DoPop(aCount,EFalse);
426 EXPORT_C void CCleanup::PopAll()
428 Pops all cleanup items at the current level, and then decrements the level.
438 EXPORT_C void CCleanup::PopAndDestroy()
440 Pops a single cleanup item from the cleanup stack, and invokes its cleanup
443 @panic E32USER-CBase 64 If there are no items on the cleanup stack.
444 @panic E32USER-CBase 63 If a cleanup level is crossed.
454 EXPORT_C void CCleanup::PopAndDestroy(TInt aCount)
456 Pops the specified number of cleanup items from the cleanup stack, and invokes
457 their cleanup operations.
459 @param aCount The number of cleanup items to be popped from the cleanup stack.
461 @panic E32USER-CBase 70 If the specified number of cleanup items is negative.
462 @panic E32USER-CBase 64 If the specifed number of items is greater than the
463 number of items on the cleanup stack.
464 @panic E32USER-CBase 63 If the specified number of items is such that it causes
465 a cleanup level to be crossed.
475 EXPORT_C void CCleanup::PopAndDestroyAll()
477 Pops all cleanup items at the current level, invokes their cleanup operations
478 and then decrements the level.
488 EXPORT_C void CCleanup::Check(TAny* aExpectedItem)
490 Checks that the cleanup item at the top of the cleanup stack
491 represents a cleanup operation for the specified object.
493 @param aExpectedItem The object which is the subject of the test.
497 TCleanupStackItem* last=iNext-1;
498 __ASSERT_ALWAYS(last>=iBase && last->Check(aExpectedItem), Panic(EClnCheckFailed));
504 EXPORT_C CTrapCleanup *CTrapCleanup::New()
506 Allocates and constructs a cleanup stack.
508 If successfully constructed, this cleanup stack becomes
509 the current cleanup stack.
511 @return A pointer to the new cleanup stack. This pointer is NULL, if allocation
516 CTrapCleanup *pT=new CTrapCleanup;
519 CCleanup *pC=CCleanup::New();
522 pT->iHandler.iCleanup=pC;
523 pT->iOldHandler=User::SetTrapHandler(&pT->iHandler);
537 EXPORT_C CTrapCleanup::CTrapCleanup()
548 EXPORT_C CTrapCleanup::~CTrapCleanup()
552 Frees resources owned by the object, prior to its destruction. This cleanup
553 stack ceases to be the current cleanup stack.
555 If there is a stack of cleanup stacks, then the next cleanup stack becomes
556 the current cleanup stack.
560 if (iHandler.iCleanup!=NULL)
562 User::SetTrapHandler(iOldHandler);
563 delete iHandler.iCleanup;
570 EXPORT_C void CleanupStack::PushL(TAny *aPtr)
572 Pushes a pointer to an object onto the cleanup stack.
574 If a leave occurs while an object is on the stack, it is cleaned
575 up automatically. Untyped objects are cleaned up with User::Free()
576 (a rather limited form of cleanup, not even the C++ destructor is called).
578 Typically, when an object has been fully constructed and it can be guaranteed
579 that a pointer to this new object is stored in some other object before a leave
580 occurs, issue CleanupStack::Pop() to pop it back off the stack.
582 If no cleanup stack has been allocated, a panic occurs.
584 It is guaranteed that the object is pushed onto the cleanup stack. However,
585 this function may leave if a stack frame for the next PushL() cannot be
586 allocated. In this case, the cleanup stack will be cleaned up as normal, and
587 no extra programmer intervention is needed.
589 @param aPtr Pointer to any object. If cleanup is necessary, the object will be
590 freed by User::Free(), which does not invoke any destructor: it
591 simply frees its memory
593 @panic E32USER-CBase 66 if a call to this function is made when no prior
594 call to TRAP has been made.
598 cleanup().PushL(aPtr);
604 EXPORT_C void CleanupStack::PushL(CBase *aPtr)
606 Pushes a pointer to an object onto the cleanup stack.
608 If a leave occurs while an object is on the stack, it is cleaned
609 up automatically. CBase derived objects are cleaned up with delete.
611 Typically, when an object has been fully constructed and it can be guaranteed
612 that a pointer to this new object is stored in some other object before a leave
613 occurs, issue CleanupStack::Pop() to pop it back off the stack.
615 If no cleanup stack has been allocated, a panic occurs.
617 It is guaranteed that the object is pushed onto the cleanup stack. However,
618 this function may leave if a stack frame for the next PushL() cannot be
619 allocated. In this case, the cleanup stack will be cleaned up as normal,
620 and no extra programmer intervention is needed.
622 @param aPtr Pointer to a CBase-derived object. If cleanup is necessary, the
623 object will be freed by delete, thus invoking its destructor,
624 and freeing its memory.
626 @panic E32USER-CBase 66 if a call to this function is made when no prior
627 call to TRAP has been made.
631 cleanup().PushL(aPtr);
637 EXPORT_C void CleanupStack::PushL(TCleanupItem anItem)
639 Pushes a cleanup item onto the cleanup stack.
641 If a leave occurs while a cleanup item is on the stack, the cleanup operation
642 defined in the construction of the TCleanupItem, is invoked.
644 Typically, when an object has been fully constructed and it can be guaranteed
645 that a pointer to this new object is stored in some other object before a leave
646 occurs, issue CleanupStack::Pop() to pop it back off the stack.
648 If no cleanup stack has been allocated, a panic occurs.
650 It is guaranteed that the object is pushed onto the cleanup stack. However,
651 this function may leave if a stack frame for the next PushL() cannot be
652 allocated. In this case, the cleanup stack will be cleaned up as normal,
653 and no extra programmer intervention is needed.
655 @param anItem A cleanup item. If cleanup is necessary, the cleanup operation
656 defined in the construction of anItem is called.
658 @panic E32USER-CBase 66 if a call to this function is made when no prior
659 call to TRAP has been made.
663 cleanup().PushL(anItem);
669 EXPORT_C void CleanupStack::Pop()
671 Pops an object previously pushed onto the cleanup stack
672 by CleanupStack::PushL().
674 After an object has been successfully constructed and stored within
675 another object, it cannot be orphaned and, therefore, the object
676 (i.e. a pointer or a cleanup item) can be popped from the cleanup stack.
678 If no cleanup stack has been allocated, or there is nothing on the stack,
689 EXPORT_C void CleanupStack::Pop(TInt aCount)
691 Pops a specified number of objects previously pushed onto the
692 cleanup stack by CleanupStack::PushL().
694 After an object has been successfully constructed and stored within another
695 object, it cannot be orphaned and, therefore, the object(s), that is, pointers
696 and cleanup items can be popped from the cleanup stack.
698 If no cleanup stack has been allocated, or there is nothing on the stack,
701 @param aCount The number of objects to be popped off the cleanup stack.
705 cleanup().Pop(aCount);
711 EXPORT_C void CleanupStack::PopAndDestroy()
713 Pops and cleans up an item pushed onto the stack.
715 If the item on the stack is a CBase* pointer, the pointer is removed from
716 the stack and the object is destroyed with delete.
718 If the item on the stack is a TAny* pointer, the pointer is removed from
719 the stack and the memory occupied by the object is freed with User::Free().
721 If the item on the stack is a cleanup item, i.e. an object of
722 type TCleanupItem, the item is removed from the stack and the cleanup
723 operation defined during construction of the TCleanupItem object is invoked.
725 If no cleanup stack has been allocated, or there is nothing on the stack,
730 cleanup().PopAndDestroy();
736 EXPORT_C void CleanupStack::PopAndDestroy(TInt aCount)
738 Pops and cleans up the specified number of items pushed onto the stack.
740 If an item on the stack is a CBase* pointer, the pointer is removed from
741 the stack and the object is destroyed with delete.
743 If an item on the stack is a TAny* pointer, the pointer is removed from the
744 stack and the memory occupied by the object is freed with User::Free().
746 If an item on the stack is a cleanup item, i.e. an object of type TCleanupItem,
747 the item is removed from the stack and the cleanup operation defined during
748 construction of the TCleanupItem object is invoked.
750 If no cleanup stack has been allocated, or there is nothing on the stack,
753 @param aCount The number of objects to be popped off the cleanup stack and
758 cleanup().PopAndDestroy(aCount);
764 EXPORT_C void CleanupStack::Check(TAny* aExpectedItem)
766 Checks that the specified object is at the top of the cleanup stack.
768 If the specified item is not at the top of the cleanup stack, then the function
769 raises an E32USER-CBase 90 panic.
771 The function is part of Symbian OS in both debug and release builds, and is
774 @param aExpectedItem A pointer to the item expected to be at the top of the
779 cleanup().Check(aExpectedItem);