idlefw/tsrc/devicestatusplugin/mt_devstaplg/DelayedFunctionCall.h
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 10:13:44 +0300
branchRCL_3
changeset 28 053c6c7c14f3
permissions -rw-r--r--
Revision: 201026 Kit: 201033

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
//DelayedFunctionCall.h
//DFC caller and templated generic function call objects.

#ifndef CDELAYEDFUNCTIONCALL_H__
#define CDELAYEDFUNCTIONCALL_H__


// INCLUDES
#include <E32base.h>


// CLASS DESCRIPTION

/**
 * Abstract interface for function call object.
 */
class MFunctionCall
    {
    public:

        /**
         * Function execution.
         *
         * Executes the function call.
         *
         * If function execution fails (e.g. leaves),
         * leave code is stored in CDelayedFunctionCall host.
         */
        virtual void InvokeL() = 0;

        virtual MFunctionCall* CloneLC() const = 0;


        /**
         * Public virtual destructor.
         *
         * Allows thus function call object deletion.
         */
        virtual ~MFunctionCall() {}
    };



// CLASS DESCRIPTION

/**
 * Delayed Function Call - caller.
 *
 * Executes DFC objects after given delay.
 */
class CDelayedFunctionCall : public CTimer
    {
    public: //Construction

        static inline CDelayedFunctionCall* NewLC();
        static inline CDelayedFunctionCall* NewL();
        inline ~CDelayedFunctionCall();

    public: //Delayed call

        /**
         * Issues DFC call. Panics if CDelayedFunctionCall object
         * is already in use.
         *
         * @param aFC The FC object to execute.
         * @param aCallDelay The delay when to execute the FC.
         * @param aFCOwnershipTransf If ETrue, the aFC object
         * ownership is transferred to DFC caller and DFC caller
         * deletes object. If EFalse, no ownership transfer is done.
         */
        inline void IssueDfc( MFunctionCall& aFC, TInt aCallDelay, TBool aFCOwnershipTransf = ETrue );


        /**
         * Similar like IssueDfc() but pushes
         * release to CleanupStack ==>
         * if there happens a leave before the DFC gets scheduled,
         * DFC is canceled.
         */
        inline void IssueDfcLC( MFunctionCall& aFC, TInt aCallDelay, TBool aFCOwnershipTransf = ETrue );


        /**
         * Releases the DFC.
         * Cancels the call and deletes possibly owned FC.
         */
        inline void Release();


        /**
         * Delayed FC error handling.
         */
        inline void LeaveIfFcFailedL();

        /**
         * Tests was the FC executed or not.
         */
        inline TBool FcExecuted();


    private:
        inline CDelayedFunctionCall();
        inline void RunL();
        inline TInt RunError( TInt aError );
        inline void InvokeL();


    private:    //data

        //REF/OWN: Function call object
        MFunctionCall*    iFC;

        //OWN: Is function call object owned
        TBool    iFCOwned;

        //OWN: Did function call leave
        TBool   iFCLeft;

        //OWN: Was function called
        TBool   iFCCalled;

        //OWN: Leave code from the function call
        TInt    iFCLeaveErr;
    };




// -----------------------------------------------------------------------------
// CDelayedFunctionCall public functions
// -----------------------------------------------------------------------------
//
inline CDelayedFunctionCall* CDelayedFunctionCall::NewLC()
    {
    CDelayedFunctionCall* self = new (ELeave) CDelayedFunctionCall();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

inline CDelayedFunctionCall* CDelayedFunctionCall::NewL()
    {
    CDelayedFunctionCall* self = NewLC();
    CleanupStack::Pop( self );
    return self;
    }


inline CDelayedFunctionCall::~CDelayedFunctionCall()
    {
    Cancel();
    if( iFCOwned )
        {
        delete iFC;
        }
    }


inline void CDelayedFunctionCall::IssueDfc( MFunctionCall& aFC,
                                            TInt aFCDelay,
                                            TBool aFCOwnershipTransf )
    {
    __ASSERT_ALWAYS( !IsActive(), User::Panic( _L("DFC caller"), KErrInUse ) );

    iFC = &aFC;
    iFCOwned = aFCOwnershipTransf;
    iFCLeft = EFalse;
    iFCLeaveErr = KErrNone;
    iFCCalled = EFalse;

    if( aFCDelay >= 0 )
        {
        After( aFCDelay );
        }
    else
        {
        InvokeL();
        }
    }


inline void CDelayedFunctionCall::IssueDfcLC( MFunctionCall& aFC,
                                              TInt aFCDelay,
                                              TBool aFCOwnershipTransf )
    {
    IssueDfc( aFC, aFCDelay, aFCOwnershipTransf );
    CleanupReleasePushL( *this );
    }


inline void CDelayedFunctionCall::Release()
    {
    Cancel();
    if( iFCOwned )
        {
        delete iFC;
        iFC = NULL;
        }
    }

inline void CDelayedFunctionCall::LeaveIfFcFailedL()
    {
    if( iFCLeft )
        {
        User::Leave( iFCLeaveErr );
        }
    }


inline TBool CDelayedFunctionCall::FcExecuted()
    {
    return iFCCalled;
    }



// -----------------------------------------------------------------------------
// CDelayedFunctionCall private functions
// -----------------------------------------------------------------------------
//
inline CDelayedFunctionCall::CDelayedFunctionCall()
    : CTimer( CActive::EPriorityHigh )
    {
    CActiveScheduler::Add( this );
    }

inline void CDelayedFunctionCall::RunL()
    {
    InvokeL();
    }

inline TInt CDelayedFunctionCall::RunError( TInt aError )
    {
    iFCLeft = ETrue;
    iFCCalled = ETrue;
    iFCLeaveErr = aError;
    if( iFCOwned )
        {
        delete iFC;
        iFC = NULL;
        }

    return KErrNone;
    }


inline void CDelayedFunctionCall::InvokeL()
    {
    iFC->InvokeL();
    iFCCalled = ETrue;
    if( iFCOwned )
        {
        delete iFC;
        iFC = NULL;
        }
    }







// =============================================================================
// Generic Function Call classes
// =============================================================================


// CLASS DESCRIPTION

/**
 * Base class for generic function call objects.
 * Initializes function call members to zero
 * during the object construction.
 */
class TMemFillBase
    {
    protected: //Protected constructor & virtual destructor
        TMemFillBase( TUint aSize ) { Mem::FillZ( this, aSize); }
        virtual ~TMemFillBase() {}
    };





// CLASS DESCRIPTION

/**
 * Generic function call object for function that returns void.
 *
 * This function call object doesn't own any of the
 * call parameters, nor the called object.
 */
template< class C,
          class P1=TInt,
          class P2=TInt,
          class P3=TInt,
          class P4=TInt >
class TGenericFuncCallVoid : public TMemFillBase, public MFunctionCall
    {
    private: //Function type shortcuts
        typedef void (C::*TFuncTypeVoid)();
        typedef void (C::*TFuncType1)( P1 aP1 );
        typedef void (C::*TFuncType2)( P1 aP1, P2 aP2 );
        typedef void (C::*TFuncType3)( P1 aP1, P2 aP2, P3 aP3 );
        typedef void (C::*TFuncType4)( P1 aP1, P2 aP2, P3 aP3, P4 aP4 );


    public: //Construction / destruction
        TGenericFuncCallVoid( C& aObj, TFuncTypeVoid aFunc )
            : TMemFillBase( sizeof( TGenericFuncCallVoid ) ),
              iObj( aObj ),
              iFVoid( aFunc )
            {}

        TGenericFuncCallVoid( C& aObj, TFuncType1 aFunc, P1 aP1 )
            : TMemFillBase( sizeof( TGenericFuncCallVoid ) ),
              iObj( aObj ),
              iF1( aFunc ),
              iP1( aP1 )
            {}

        TGenericFuncCallVoid( C& aObj, TFuncType2 aFunc, P1 aP1, P2 aP2  )
            : TMemFillBase( sizeof( TGenericFuncCallVoid ) ),
              iObj( aObj ),
              iF2( aFunc ),
              iP1( aP1 ), iP2( aP2 )
            {}

        TGenericFuncCallVoid( C& aObj, TFuncType3 aFunc, P1 aP1 , P2 aP2, P3 aP3  )
            : TMemFillBase( sizeof( TGenericFuncCallVoid ) ),
              iObj( aObj ),
              iF3( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 )
            {}

        TGenericFuncCallVoid( C& aObj, TFuncType4 aFunc, P1 aP1 , P2 aP2, P3 aP3, P4 aP4 )
            : TMemFillBase( sizeof( TGenericFuncCallVoid ) ),
              iObj( aObj ),
              iF4( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 ), iP4( aP4 )
            {}

        ~TGenericFuncCallVoid()
            {}

    private: //From MFunctionCall

        void InvokeL()
            {
            if( iFVoid )
                {
                (iObj.*iFVoid)();
                }
            else if( iF1 )
                {
                (iObj.*iF1)( iP1 );
                }
            else if( iF2 )
                {
                (iObj.*iF2)( iP1, iP2 );
                }
            else if( iF3 )
                {
                (iObj.*iF3)( iP1, iP2, iP3 );
                }
            else if( iF4 )
                {
                (iObj.*iF4)( iP1, iP2, iP3, iP4 );
                }
            }

        MFunctionCall* TGenericFuncCallVoid::CloneLC() const
            {
			TAny* self = User::AllocL( sizeof( TGenericFuncCallVoid ) );
            Mem::Copy( self, this, sizeof( TGenericFuncCallVoid ) );
            TGenericFuncCallVoid* self2 = (TGenericFuncCallVoid*) self;
            CleanupDeletePushL( self2 );
            return (MFunctionCall*) self2;
            }


    private: //Call data

        C& iObj;
        P1 iP1;
        P2 iP2;
        P3 iP3;
        P4 iP4;
        TFuncTypeVoid iFVoid;
        TFuncType1 iF1;
        TFuncType2 iF2;
        TFuncType3 iF3;
        TFuncType4 iF4;
    };





// CLASS DESCRIPTION

/**
 * Generic function call object for function that returns a value
 * (with by-value convention).
 *
 * This function call object doesn't own any of the
 * call parameters, nor the called object or the result.
 */
template< class C,
          class R,
          class P1=TInt,
          class P2=TInt,
          class P3=TInt,
          class P4=TInt >
class TGenericFuncCallRetByValue : public TMemFillBase, public MFunctionCall
    {
    private: //Function type shortcuts
        typedef R (C::*TFuncTypeVoid)();
        typedef R (C::*TFuncType1)( P1 aP1 );
        typedef R (C::*TFuncType2)( P1 aP1, P2 aP2 );
        typedef R (C::*TFuncType3)( P1 aP1, P2 aP2, P3 aP3 );
        typedef R (C::*TFuncType4)( P1 aP1, P2 aP2, P3 aP3, P4 aP4 );


    public: //Construction / destruction
        TGenericFuncCallRetByValue( C& aObj, TFuncTypeVoid aFunc )
            : TMemFillBase( sizeof( TGenericFuncCallRetByValue ) ),
              iObj( aObj ),
              iFVoid( aFunc )
            {}

        TGenericFuncCallRetByValue( C& aObj, TFuncType1 aFunc, P1 aP1 )
            : TMemFillBase( sizeof( TGenericFuncCallRetByValue ) ),
              iObj( aObj ),
              iF1( aFunc ),
              iP1( aP1 )
            {}

        TGenericFuncCallRetByValue( C& aObj, TFuncType2 aFunc, P1 aP1, P2 aP2  )
            : TMemFillBase( sizeof( TGenericFuncCallRetByValue ) ),
              iObj( aObj ),
              iF2( aFunc ),
              iP1( aP1 ), iP2( aP2 )
            {}

        TGenericFuncCallRetByValue( C& aObj, TFuncType3 aFunc, P1 aP1 , P2 aP2, P3 aP3  )
            : TMemFillBase( sizeof( TGenericFuncCallRetByValue ) ),
              iObj( aObj ),
              iF3( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 )
            {}

        TGenericFuncCallRetByValue( C& aObj, TFuncType4 aFunc, P1 aP1 , P2 aP2, P3 aP3, P4 aP4 )
            : TMemFillBase( sizeof( TGenericFuncCallRetByValue ) ),
              iObj( aObj ),
              iF4( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 ), iP4( aP4 )
            {}

        ~TGenericFuncCallRetByValue()
            {}

    private: //From MFunctionCall

        void InvokeL()
            {
            if( iFVoid )
                {
                iReturnValue = (iObj.*iFVoid)();
                }
            else if( iF1 )
                {
                iReturnValue = (iObj.*iF1)( iP1 );
                }
            else if( iF2 )
                {
                iReturnValue = (iObj.*iF2)( iP1, iP2 );
                }
            else if( iF3 )
                {
                iReturnValue = (iObj.*iF3)( iP1, iP2, iP3 );
                }
            else if( iF4 )
                {
                iReturnValue = (iObj.*iF4)( iP1, iP2, iP3, iP4 );
                }
            }

        MFunctionCall* TGenericFuncCallRetByValue::CloneLC() const
            {
			TAny* self = User::AllocL( sizeof( TGenericFuncCallRetByValue ) );
            Mem::Copy( self, this, sizeof( TGenericFuncCallRetByValue ) );
            TGenericFuncCallRetByValue* self2 = (TGenericFuncCallRetByValue*) self;
            CleanupDeletePushL( self2 );
            return (MFunctionCall*) self2;
            }

    private: //Call data

        C& iObj;
        P1 iP1;
        P2 iP2;
        P3 iP3;
        P4 iP4;
        TFuncTypeVoid iFVoid;
        TFuncType1 iF1;
        TFuncType2 iF2;
        TFuncType3 iF3;
        TFuncType4 iF4;

    public: //Return value

        R iReturnValue;
    };




template< class P1=TInt,
          class P2=TInt,
          class P3=TInt,
          class P4=TInt >
class TGenericGlobalFuncCallVoid : public TMemFillBase, public MFunctionCall
    {
    private: //Function type shortcuts
        typedef void (*TFuncTypeVoid)();
        typedef void (*TFuncType1)( P1 aP1 );
        typedef void (*TFuncType2)( P1 aP1, P2 aP2 );
        typedef void (*TFuncType3)( P1 aP1, P2 aP2, P3 aP3 );
        typedef void (*TFuncType4)( P1 aP1, P2 aP2, P3 aP3, P4 aP4 );


    public: //Construction / destruction
        TGenericGlobalFuncCallVoid( TFuncTypeVoid aFunc )
            : TMemFillBase( sizeof( TGenericGlobalFuncCallVoid ) ),
              iFVoid( aFunc )
            {}

        TGenericGlobalFuncCallVoid( TFuncType1 aFunc, P1 aP1 )
            : TMemFillBase( sizeof( TGenericGlobalFuncCallVoid ) ),
              iF1( aFunc ),
              iP1( aP1 )
            {}

        TGenericGlobalFuncCallVoid( TFuncType2 aFunc, P1 aP1, P2 aP2  )
            : TMemFillBase( sizeof( TGenericGlobalFuncCallVoid ) ),
              iF2( aFunc ),
              iP1( aP1 ), iP2( aP2 )
            {}

        TGenericGlobalFuncCallVoid( TFuncType3 aFunc, P1 aP1 , P2 aP2, P3 aP3  )
            : TMemFillBase( sizeof( TGenericGlobalFuncCallVoid ) ),
              iF3( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 )
            {}

        TGenericGlobalFuncCallVoid( TFuncType4 aFunc, P1 aP1 , P2 aP2, P3 aP3, P4 aP4 )
            : TMemFillBase( sizeof( TGenericGlobalFuncCallVoid ) ),
              iF4( aFunc ),
              iP1( aP1 ), iP2( aP2 ), iP3( aP3 ), iP4( aP4 )
            {}

        ~TGenericGlobalFuncCallVoid()
            {}

    private: //From MFunctionCall

        void InvokeL()
            {
            if( iFVoid )
                {
                (*iFVoid)();
                }
            else if( iF1 )
                {
                (*iF1)( iP1 );
                }
            else if( iF2 )
                {
                (*iF2)( iP1, iP2 );
                }
            else if( iF3 )
                {
                (*iF3)( iP1, iP2, iP3 );
                }
            else if( iF4 )
                {
                (*iF4)( iP1, iP2, iP3, iP4 );
                }
            }

        MFunctionCall* TGenericGlobalFuncCallVoid::CloneLC() const
            {
			TAny* self = User::AllocL( sizeof( TGenericGlobalFuncCallVoid ) );
            Mem::Copy( self, this, sizeof( TGenericGlobalFuncCallVoid ) );
            TGenericGlobalFuncCallVoid* self2 = (TGenericGlobalFuncCallVoid*) self;
            CleanupDeletePushL( self2 );
            return (MFunctionCall*) self2;
            }

    private: //Call data

        P1 iP1;
        P2 iP2;
        P3 iP3;
        P4 iP4;
        TFuncTypeVoid iFVoid;
        TFuncType1 iF1;
        TFuncType2 iF2;
        TFuncType3 iF3;
        TFuncType4 iF4;
    };




// CLASS DESCRIPTION


/**
 * Generic function call object to delete objects.
 *
 * This function call object doesn't own any of the
 * parameters ==> the objects are deleted only when
 * the DFC is executed.
 *
 * If deleted objects are provided as pointer reference ( Class*& ),
 * the original pointer to object (e.g. class member)
 * is set to NULL during the deletion.
 */
template< class C1,
          class C2 = TAny*,
          class C3 = TAny* >
class TGenericObjDelete : public TMemFillBase, public MFunctionCall
    {
    public: //Construction / destruction
        explicit TGenericObjDelete( C1 aObj1 )
            : TMemFillBase( sizeof( TGenericObjDelete ) ),
              iObj1( aObj1 )
            {}

        TGenericObjDelete( C1 aObj1, C2 aObj2 )
            : TMemFillBase( sizeof( TGenericObjDelete ) ),
              iObj1( aObj1 ),
              iObj2( aObj2 )
            {}

        TGenericObjDelete( C1 aObj1, C2 aObj2, C3 aObj3 )
            : TMemFillBase( sizeof( TGenericObjDelete ) ),
              iObj1( aObj1 ),
              iObj2( aObj2 ),
              iObj3( aObj3 )
            {}

        ~TGenericObjDelete()
            {}

    private: //From MFunctionCall

        void InvokeL()
            {
            delete iObj1;
            iObj1 = NULL;

            delete iObj2;
            iObj2 = NULL;

            delete iObj3;
            iObj3 = NULL;
            }

        MFunctionCall* TGenericObjDelete::CloneLC() const
            {
			TAny* self = User::AllocL( sizeof( TGenericObjDelete ) );
            Mem::Copy( self, this, sizeof( TGenericObjDelete ) );
            TGenericObjDelete* self2 = (TGenericObjDelete*) self;
            CleanupDeletePushL( self2 );
            return (MFunctionCall*) self2;
            }

    private: //Call data

        C1 iObj1;
        C2 iObj2;
        C3 iObj3;
    };


#endif // CDELAYEDFUNCTIONCALL_H__


// End of File