filemanager/Engine/src/CFileManagerThreadWrapper.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 20:09:41 +0200
changeset 0 6a9f87576119
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2006-2007 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:  Background thread functionality wrapper
*
*/



// INCLUDE FILES
#include "CFileManagerThreadWrapper.h"
#include "FileManagerDebug.h"


// ============================= MEMBER FUNCTIONS =============================

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CFileManagerThreadWrapper()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper::CFileManagerThreadWrapper() :
    CActive( CActive::EPriorityStandard )
    {
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::~CFileManagerThreadWrapper()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper::~CFileManagerThreadWrapper()
    {
    Cancel();
    delete iNotifyObserver;
    iSemaphore.Close();
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::NewL()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper* CFileManagerThreadWrapper::NewL()
    {
    CFileManagerThreadWrapper* self =
        new (ELeave) CFileManagerThreadWrapper();

    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::ConstructL()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::ConstructL()
    {
    CActiveScheduler::Add( this );
    User::LeaveIfError( iSemaphore.CreateLocal( 0 ) );
    iNotifyObserver = CNotifyObserver::NewL( *this );
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::RunL()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::RunL()
    {
    iNotifyObserver->Cancel();

    TInt err( iStatus.Int() );
    LOG_IF_ERROR1( err, "CFileManagerThreadWrapper::RunL()-err=%d", err )

    if ( iNotify & MFileManagerThreadFunction::ENotifyFinished )
        {
        TRAP_IGNORE( iFunction->NotifyThreadClientL(
            MFileManagerThreadFunction::ENotifyFinished, err ) );
        }
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::DoNotifyL()
//
// ----------------------------------------------------------------------------

void CFileManagerThreadWrapper::DoNotifyL( TInt aErr )
    {
    LOG_IF_ERROR1( aErr, "CFileManagerThreadWrapper::DoNotifyL()-aErr=%d", aErr )

    iResumePending = ETrue;

    if ( aErr != KErrNone &&
        ( iNotify & MFileManagerThreadFunction::ENotifyError ) )
        {
        iFunction->NotifyThreadClientL(
            MFileManagerThreadFunction::ENotifyError, aErr );
        }
    else if ( iNotify & MFileManagerThreadFunction::ENotifyStepFinished )
        {
        iFunction->NotifyThreadClientL(
            MFileManagerThreadFunction::ENotifyStepFinished, aErr );
        }
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::RunError()
//
// ----------------------------------------------------------------------------
TInt CFileManagerThreadWrapper::RunError( TInt aErr )
    {
    if ( aErr != KErrNone )
        {
        ERROR_LOG1( "CFileManagerThreadWrapper::RunError()-err=%d", aErr )
        iCancel = ETrue;
        ResumeThread();
        }
    return aErr;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::DoCancel()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::DoCancel()
    {
    FUNC_LOG

    CancelThread();
    iSemaphore.Signal(); // To avoid deadlock
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::StartThread()
//
// ----------------------------------------------------------------------------
TInt CFileManagerThreadWrapper::StartThread(
        MFileManagerThreadFunction& aFunction,
        TUint aNotify,
        TThreadPriority aPriority )
    {
    FUNC_LOG

    TInt err( KErrAlreadyExists );

    if ( !IsActive() )
        {
        RThread thread;
        err = thread.Create(
            KNullDesC, ThreadFunction, KDefaultStackSize, NULL, this );
        if ( err == KErrNone )
            {
            thread.SetPriority( aPriority );
            thread.Logon( iStatus );

            iClientId = RThread().Id();
            iFunction = &aFunction;
            iNotify = aNotify;
            iCancel = EFalse;

            iNotifyObserver->Activate();
            SetActive();

            thread.Resume();
            thread.Close();
            }
        }

    LOG_IF_ERROR1( err, "CFileManagerThreadWrapper::StartThread()-err=%d",
        err )

    return err;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::ThreadFunction()
//
// ----------------------------------------------------------------------------
TInt CFileManagerThreadWrapper::ThreadFunction( TAny* ptr )
    {
    FUNC_LOG

    CFileManagerThreadWrapper* self =
        static_cast< CFileManagerThreadWrapper* >( ptr );

    CTrapCleanup* cleanupStack = CTrapCleanup::New();
    if ( !cleanupStack )
        {
        return KErrNoMemory;
        }

    TRAPD( err, self->ThreadFunctionL() );

    self->iFunction->ReleaseThread();

    delete cleanupStack;

    return err;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::ThreadFunctionL()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::ThreadFunctionL()
    {
    FUNC_LOG

    iFunction->InitThreadL();

    while ( !iCancel )
        {
        TRAPD( err, iFunction->ThreadStepL() );

        if ( !iCancel )
            {
            if ( err != KErrNone &&
                ( iNotify & MFileManagerThreadFunction::ENotifyError ) )
                {
                User::LeaveIfError( NotifyClientAndWaitConfirm( err ) );
                }
            else if ( iNotify &
                MFileManagerThreadFunction::ENotifyStepFinished )
                {
                User::LeaveIfError( NotifyClientAndWaitConfirm( err ) );
                }
            else
                {
                User::LeaveIfError( err );
                }
            }
        if ( iFunction->IsThreadDone() )
            {
            break;
            }
        }

    if ( iCancel )
        {
        User::LeaveIfError( KErrCancel );
        }
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CancelThread()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::CancelThread()
    {
    FUNC_LOG

    iCancel = ETrue;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::IsThreadCanceled()
//
// ----------------------------------------------------------------------------
TBool CFileManagerThreadWrapper::IsThreadCanceled() const
    {
    return iCancel;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::NotifyClientAndWaitConfirm()
//
// ----------------------------------------------------------------------------
TInt CFileManagerThreadWrapper::NotifyClientAndWaitConfirm( TInt aErr )
    {
    FUNC_LOG

    RThread client;
    TInt err( client.Open( iClientId ) );

    if ( err == KErrNone )
        {
        iNotifyObserver->Complete( client, aErr );
        client.Close();
        iSemaphore.Wait(); // Wait resume from client
        }
    return err;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::ResumeThread()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::ResumeThread()
    {
    FUNC_LOG

    if ( !iNotifyObserver->IsActive() && iResumePending )
        {
        iResumePending = EFalse;
        iNotifyObserver->Activate();
        iSemaphore.Signal(); // Resume thread stepping
        }
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::IsThreadStarted()
//
// ----------------------------------------------------------------------------
TBool CFileManagerThreadWrapper::IsThreadStarted() const
    {
    return IsActive();
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::CNotifyObserver()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper::CNotifyObserver::CNotifyObserver(
    CFileManagerThreadWrapper& aWrapper ) :
        CActive( CActive::EPriorityStandard ),
        iWrapper( aWrapper )
    {
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::NewL()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper::CNotifyObserver*
    CFileManagerThreadWrapper::CNotifyObserver::NewL(
        CFileManagerThreadWrapper& aWrapper )
    {
    CNotifyObserver* self = new (ELeave) CNotifyObserver( aWrapper );
    CActiveScheduler::Add( self );
    return self;
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::~CNotifyObserver()
//
// ----------------------------------------------------------------------------
CFileManagerThreadWrapper::CNotifyObserver::~CNotifyObserver()
    {
    Cancel();
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::RunL()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::CNotifyObserver::RunL()
    {
    iWrapper.DoNotifyL( iStatus.Int() );
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::RunError()
//
// ----------------------------------------------------------------------------
TInt CFileManagerThreadWrapper::CNotifyObserver::RunError( TInt aErr )
    {
    return iWrapper.RunError( aErr );
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::DoCancel()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::CNotifyObserver::DoCancel()
    {
    // Just complete status immediately since
    // background thread does not complete status anymore
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrCancel );
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::Activate()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::CNotifyObserver::Activate()
    {
    if ( !IsActive() )
        {
        iStatus = KRequestPending;
        SetActive();
        }
    }

// ----------------------------------------------------------------------------
// CFileManagerThreadWrapper::CNotifyObserver::Complete()
//
// ----------------------------------------------------------------------------
void CFileManagerThreadWrapper::CNotifyObserver::Complete(
    RThread& aThread, TInt aResult )
    {
    if ( IsActive() )
        {
        TRequestStatus* status = &iStatus;
        aThread.RequestComplete( status, aResult );
        }
    }

// End of File