Cleanup support for ResetAndDestroy()
After some looking into the matter I've decided that either there is no way to do this using the standard Symbian API or I that I am too blind to find one, I wrote one myself.
The point is to make a dynamic array's ResetAndDestroy() method being called for an array pushed onto the cleanup stack upon a leave or an explicit call to PopAndDestroy(). While this functionality might be rarely necessary or desired, there are cases where allocating an dynamic array on the heap is the most elegant solution. This approach requires efficient and clean cleanup support, and here's how I've addressed the problem.
In practice, here's how it's used (code simplified and lacking error checking etc.):
SomeCode.cpp:
..
RPointerArray<CMyType>* list = new RPointerArray<CMyType>( 1 );
CleanupResetAndDestroyPushL( list );
// add stuff to list
// use list
CleanupStack::PopAndDestroy(); // list
What happens in PopAndDestroy():
- . list->ResetAndDestroy();
- . delete list;
The following code is from my soon-to-be-released project Nova3D, written under the LGPL licence.
CleanupResetAndDestroy.h:
* $Id: CleanupResetAndDestroy.h,v 1.1 2004/10/16 11:02:37 matti Exp $
*
* Nova 3D Engine - A real-time 3D graphics framework for Symbian environments
* Copyright (C) 2001-2004 Matti Dahlbom
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Matti Dahlbom <matti at 777-team dot org>
*/
#ifndef __CLEANUPRESETANDDESTROY_H
#define __CLEANUPRESETANDDESTROY_H
#include <e32base.h>
template <class T> void CleanupResetAndDestroyPushL( T* aObj );
/**
* Utility template class to perform thorough cleanup for classes like
* RPointerArray; upon cleanup, ResetAndDestroy() is called for the object
* after which the object itself is deleted.
*
* @author Matti Dahlbom
* @version $Name: $, $Revision: 1.1 $
*/
template <class T> class TCleanupResetAndDestroy : public CBase
{
private: // Constructors and desctructor
inline TCleanupResetAndDestroy( T* aObj );
inline ~TCleanupResetAndDestroy();
private: // Data
T* iObj;
#ifdef __WINS__
// MSVC++ way
friend void CleanupResetAndDestroyPushL( T* aObj );
#else
// gcc way
friend void CleanupResetAndDestroyPushL<>( T* aObj );
#endif
};
//=================================================
// template class method implementations
//=================================================
template <class T> TCleanupResetAndDestroy<T>::TCleanupResetAndDestroy( T* aObj )
: iObj( aObj )
{
}
template <class T> TCleanupResetAndDestroy<T>::~TCleanupResetAndDestroy()
{
iObj->ResetAndDestroy();
delete iObj;
}
/**
* Pushes an object on cleanup stack. Object's ResetAndDestroy() will be called
* upon cleanup.
*/
template <class T> inline void CleanupResetAndDestroyPushL( T* aObj )
{
TCleanupResetAndDestroy<T>* item = new (ELeave) TCleanupResetAndDestroy<T>( aObj );
CleanupStack::PushL( item );
}
#endif






> Cleanup support for ResetAndDestroy()
Actually there is Symbian API support for this kind of behaviour.
Implement a cleanup method taking a TAny* parameter like void CleanupArray(TAny* aObj); and inside that method cast the aObj to correct array type and then call ResetAndDestroy().
To use the cleanup method push a TCleanupItem to the cleanup stack: RPointerArray<CMyType>* list = new RPointerArray<CMyType>( 1 ); CleanupStack::PushL(TCleanupItem(CleanupArray, list)); //... CleanupStack::PopAndDestroy();
> Cleanup support for ResetAndDestroy()
> Cleanup support for ResetAndDestroy()
Actually there is an entire implementation of this already provided in Symbian 7.0s in the mmf\common\mmfcontrollerpluginresolver.h class
No I don't kno why it was put there and I know the some of the guys in Symbian that wrote the MMF module!
> Cleanup support for ResetAndDestroy()
> Cleanup support for ResetAndDestroy()
There is a subtle flaw in this, in that if the first line of the CleanupResetAndDestroyPushL method leaves then the array does not get cleaned up.
All the standard clean up stack functions guarantee that they take ownership of the object passed in. To do this they make sure that there is always at least one spare slot on the clean up stack. If a call to CleanupStack::PushL or CleanupClosePushL (or others) uses the last available slot, the stack will allocate more memory, which could cause a leave, which is why all the xxxPushL functions can leave. If a leave occurs, the object that was pushed on is destroyed along with the rest of the clean up items on the stack. Doing any kind of leaving operation in a CleanupResetAndDestroyPushL style function before the item is on the clean up stack is unsafe.