|         |      1 /* | 
|         |      2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). | 
|         |      3 * All rights reserved. | 
|         |      4 * This component and the accompanying materials are made available | 
|         |      5 * under the terms of "Eclipse Public License v1.0"" | 
|         |      6 * which accompanies this distribution, and is available | 
|         |      7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". | 
|         |      8 * | 
|         |      9 * Initial Contributors: | 
|         |     10 * Nokia Corporation - initial contribution. | 
|         |     11 * | 
|         |     12 * Contributors: | 
|         |     13 * | 
|         |     14 * Description:  Background thread functionality wrapper | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18  | 
|         |     19  | 
|         |     20 // INCLUDE FILES | 
|         |     21 #include "CFileManagerThreadWrapper.h" | 
|         |     22 #include "FileManagerDebug.h" | 
|         |     23  | 
|         |     24  | 
|         |     25 // ============================= MEMBER FUNCTIONS ============================= | 
|         |     26  | 
|         |     27 // ---------------------------------------------------------------------------- | 
|         |     28 // CFileManagerThreadWrapper::CFileManagerThreadWrapper() | 
|         |     29 // | 
|         |     30 // ---------------------------------------------------------------------------- | 
|         |     31 CFileManagerThreadWrapper::CFileManagerThreadWrapper() : | 
|         |     32     CActive( CActive::EPriorityStandard ) | 
|         |     33     { | 
|         |     34     } | 
|         |     35  | 
|         |     36 // ---------------------------------------------------------------------------- | 
|         |     37 // CFileManagerThreadWrapper::~CFileManagerThreadWrapper() | 
|         |     38 // | 
|         |     39 // ---------------------------------------------------------------------------- | 
|         |     40 CFileManagerThreadWrapper::~CFileManagerThreadWrapper() | 
|         |     41     { | 
|         |     42     Cancel(); | 
|         |     43     delete iNotifyObserver; | 
|         |     44     iSemaphore.Close(); | 
|         |     45     } | 
|         |     46  | 
|         |     47 // ---------------------------------------------------------------------------- | 
|         |     48 // CFileManagerThreadWrapper::NewL() | 
|         |     49 // | 
|         |     50 // ---------------------------------------------------------------------------- | 
|         |     51 CFileManagerThreadWrapper* CFileManagerThreadWrapper::NewL() | 
|         |     52     { | 
|         |     53     CFileManagerThreadWrapper* self = | 
|         |     54         new (ELeave) CFileManagerThreadWrapper(); | 
|         |     55  | 
|         |     56     CleanupStack::PushL( self ); | 
|         |     57     self->ConstructL(); | 
|         |     58     CleanupStack::Pop( self ); | 
|         |     59     return self; | 
|         |     60     } | 
|         |     61  | 
|         |     62 // ---------------------------------------------------------------------------- | 
|         |     63 // CFileManagerThreadWrapper::ConstructL() | 
|         |     64 // | 
|         |     65 // ---------------------------------------------------------------------------- | 
|         |     66 void CFileManagerThreadWrapper::ConstructL() | 
|         |     67     { | 
|         |     68     CActiveScheduler::Add( this ); | 
|         |     69     User::LeaveIfError( iSemaphore.CreateLocal( 0 ) ); | 
|         |     70     iNotifyObserver = CNotifyObserver::NewL( *this ); | 
|         |     71     } | 
|         |     72  | 
|         |     73 // ---------------------------------------------------------------------------- | 
|         |     74 // CFileManagerThreadWrapper::RunL() | 
|         |     75 // | 
|         |     76 // ---------------------------------------------------------------------------- | 
|         |     77 void CFileManagerThreadWrapper::RunL() | 
|         |     78     { | 
|         |     79     iNotifyObserver->Cancel(); | 
|         |     80  | 
|         |     81     TInt err( iStatus.Int() ); | 
|         |     82     LOG_IF_ERROR1( err, "CFileManagerThreadWrapper::RunL()-err=%d", err ) | 
|         |     83  | 
|         |     84     if ( iNotify & MFileManagerThreadFunction::ENotifyFinished ) | 
|         |     85         { | 
|         |     86         TRAP_IGNORE( iFunction->NotifyThreadClientL( | 
|         |     87             MFileManagerThreadFunction::ENotifyFinished, err ) ); | 
|         |     88         } | 
|         |     89     } | 
|         |     90  | 
|         |     91 // ---------------------------------------------------------------------------- | 
|         |     92 // CFileManagerThreadWrapper::DoNotifyL() | 
|         |     93 // | 
|         |     94 // ---------------------------------------------------------------------------- | 
|         |     95  | 
|         |     96 void CFileManagerThreadWrapper::DoNotifyL( TInt aErr ) | 
|         |     97     { | 
|         |     98     LOG_IF_ERROR1( aErr, "CFileManagerThreadWrapper::DoNotifyL()-aErr=%d", aErr ) | 
|         |     99  | 
|         |    100     iResumePending = ETrue; | 
|         |    101  | 
|         |    102     if ( aErr != KErrNone && | 
|         |    103         ( iNotify & MFileManagerThreadFunction::ENotifyError ) ) | 
|         |    104         { | 
|         |    105         iFunction->NotifyThreadClientL( | 
|         |    106             MFileManagerThreadFunction::ENotifyError, aErr ); | 
|         |    107         } | 
|         |    108     else if ( iNotify & MFileManagerThreadFunction::ENotifyStepFinished ) | 
|         |    109         { | 
|         |    110         iFunction->NotifyThreadClientL( | 
|         |    111             MFileManagerThreadFunction::ENotifyStepFinished, aErr ); | 
|         |    112         } | 
|         |    113     } | 
|         |    114  | 
|         |    115 // ---------------------------------------------------------------------------- | 
|         |    116 // CFileManagerThreadWrapper::RunError() | 
|         |    117 // | 
|         |    118 // ---------------------------------------------------------------------------- | 
|         |    119 TInt CFileManagerThreadWrapper::RunError( TInt aErr ) | 
|         |    120     { | 
|         |    121     if ( aErr != KErrNone ) | 
|         |    122         { | 
|         |    123         ERROR_LOG1( "CFileManagerThreadWrapper::RunError()-err=%d", aErr ) | 
|         |    124         iCancel = ETrue; | 
|         |    125         ResumeThread(); | 
|         |    126         } | 
|         |    127     return aErr; | 
|         |    128     } | 
|         |    129  | 
|         |    130 // ---------------------------------------------------------------------------- | 
|         |    131 // CFileManagerThreadWrapper::DoCancel() | 
|         |    132 // | 
|         |    133 // ---------------------------------------------------------------------------- | 
|         |    134 void CFileManagerThreadWrapper::DoCancel() | 
|         |    135     { | 
|         |    136     FUNC_LOG | 
|         |    137  | 
|         |    138     CancelThread(); | 
|         |    139     iSemaphore.Signal(); // To avoid deadlock | 
|         |    140     } | 
|         |    141  | 
|         |    142 // ---------------------------------------------------------------------------- | 
|         |    143 // CFileManagerThreadWrapper::StartThread() | 
|         |    144 // | 
|         |    145 // ---------------------------------------------------------------------------- | 
|         |    146 TInt CFileManagerThreadWrapper::StartThread( | 
|         |    147         MFileManagerThreadFunction& aFunction, | 
|         |    148         TUint aNotify, | 
|         |    149         TThreadPriority aPriority ) | 
|         |    150     { | 
|         |    151     FUNC_LOG | 
|         |    152  | 
|         |    153     TInt err( KErrAlreadyExists ); | 
|         |    154  | 
|         |    155     if ( !IsActive() ) | 
|         |    156         { | 
|         |    157         RThread thread; | 
|         |    158         err = thread.Create( | 
|         |    159             KNullDesC, ThreadFunction, KDefaultStackSize, NULL, this ); | 
|         |    160         if ( err == KErrNone ) | 
|         |    161             { | 
|         |    162             thread.SetPriority( aPriority ); | 
|         |    163             thread.Logon( iStatus ); | 
|         |    164  | 
|         |    165             iClientId = RThread().Id(); | 
|         |    166             iFunction = &aFunction; | 
|         |    167             iNotify = aNotify; | 
|         |    168             iCancel = EFalse; | 
|         |    169  | 
|         |    170             iNotifyObserver->Activate(); | 
|         |    171             SetActive(); | 
|         |    172  | 
|         |    173             thread.Resume(); | 
|         |    174             thread.Close(); | 
|         |    175             } | 
|         |    176         } | 
|         |    177  | 
|         |    178     LOG_IF_ERROR1( err, "CFileManagerThreadWrapper::StartThread()-err=%d", | 
|         |    179         err ) | 
|         |    180  | 
|         |    181     return err; | 
|         |    182     } | 
|         |    183  | 
|         |    184 // ---------------------------------------------------------------------------- | 
|         |    185 // CFileManagerThreadWrapper::ThreadFunction() | 
|         |    186 // | 
|         |    187 // ---------------------------------------------------------------------------- | 
|         |    188 TInt CFileManagerThreadWrapper::ThreadFunction( TAny* ptr ) | 
|         |    189     { | 
|         |    190     FUNC_LOG | 
|         |    191  | 
|         |    192     CFileManagerThreadWrapper* self = | 
|         |    193         static_cast< CFileManagerThreadWrapper* >( ptr ); | 
|         |    194  | 
|         |    195     CTrapCleanup* cleanupStack = CTrapCleanup::New(); | 
|         |    196     if ( !cleanupStack ) | 
|         |    197         { | 
|         |    198         return KErrNoMemory; | 
|         |    199         } | 
|         |    200  | 
|         |    201     TRAPD( err, self->ThreadFunctionL() ); | 
|         |    202  | 
|         |    203     self->iFunction->ReleaseThread(); | 
|         |    204  | 
|         |    205     delete cleanupStack; | 
|         |    206  | 
|         |    207     return err; | 
|         |    208     } | 
|         |    209  | 
|         |    210 // ---------------------------------------------------------------------------- | 
|         |    211 // CFileManagerThreadWrapper::ThreadFunctionL() | 
|         |    212 // | 
|         |    213 // ---------------------------------------------------------------------------- | 
|         |    214 void CFileManagerThreadWrapper::ThreadFunctionL() | 
|         |    215     { | 
|         |    216     FUNC_LOG | 
|         |    217  | 
|         |    218     iFunction->InitThreadL(); | 
|         |    219  | 
|         |    220     while ( !iCancel ) | 
|         |    221         { | 
|         |    222         TRAPD( err, iFunction->ThreadStepL() ); | 
|         |    223  | 
|         |    224         if ( !iCancel ) | 
|         |    225             { | 
|         |    226             if ( err != KErrNone && | 
|         |    227                 ( iNotify & MFileManagerThreadFunction::ENotifyError ) ) | 
|         |    228                 { | 
|         |    229                 User::LeaveIfError( NotifyClientAndWaitConfirm( err ) ); | 
|         |    230                 } | 
|         |    231             else if ( iNotify & | 
|         |    232                 MFileManagerThreadFunction::ENotifyStepFinished ) | 
|         |    233                 { | 
|         |    234                 User::LeaveIfError( NotifyClientAndWaitConfirm( err ) ); | 
|         |    235                 } | 
|         |    236             else | 
|         |    237                 { | 
|         |    238                 User::LeaveIfError( err ); | 
|         |    239                 } | 
|         |    240             } | 
|         |    241         if ( iFunction->IsThreadDone() ) | 
|         |    242             { | 
|         |    243             break; | 
|         |    244             } | 
|         |    245         } | 
|         |    246  | 
|         |    247     if ( iCancel ) | 
|         |    248         { | 
|         |    249         User::LeaveIfError( KErrCancel ); | 
|         |    250         } | 
|         |    251     } | 
|         |    252  | 
|         |    253 // ---------------------------------------------------------------------------- | 
|         |    254 // CFileManagerThreadWrapper::CancelThread() | 
|         |    255 // | 
|         |    256 // ---------------------------------------------------------------------------- | 
|         |    257 void CFileManagerThreadWrapper::CancelThread() | 
|         |    258     { | 
|         |    259     FUNC_LOG | 
|         |    260  | 
|         |    261     iCancel = ETrue; | 
|         |    262     } | 
|         |    263  | 
|         |    264 // ---------------------------------------------------------------------------- | 
|         |    265 // CFileManagerThreadWrapper::IsThreadCanceled() | 
|         |    266 // | 
|         |    267 // ---------------------------------------------------------------------------- | 
|         |    268 TBool CFileManagerThreadWrapper::IsThreadCanceled() const | 
|         |    269     { | 
|         |    270     return iCancel; | 
|         |    271     } | 
|         |    272  | 
|         |    273 // ---------------------------------------------------------------------------- | 
|         |    274 // CFileManagerThreadWrapper::NotifyClientAndWaitConfirm() | 
|         |    275 // | 
|         |    276 // ---------------------------------------------------------------------------- | 
|         |    277 TInt CFileManagerThreadWrapper::NotifyClientAndWaitConfirm( TInt aErr ) | 
|         |    278     { | 
|         |    279     FUNC_LOG | 
|         |    280  | 
|         |    281     RThread client; | 
|         |    282     TInt err( client.Open( iClientId ) ); | 
|         |    283  | 
|         |    284     if ( err == KErrNone ) | 
|         |    285         { | 
|         |    286         iNotifyObserver->Complete( client, aErr ); | 
|         |    287         client.Close(); | 
|         |    288         iSemaphore.Wait(); // Wait resume from client | 
|         |    289         } | 
|         |    290     return err; | 
|         |    291     } | 
|         |    292  | 
|         |    293 // ---------------------------------------------------------------------------- | 
|         |    294 // CFileManagerThreadWrapper::ResumeThread() | 
|         |    295 // | 
|         |    296 // ---------------------------------------------------------------------------- | 
|         |    297 void CFileManagerThreadWrapper::ResumeThread() | 
|         |    298     { | 
|         |    299     FUNC_LOG | 
|         |    300  | 
|         |    301     if ( !iNotifyObserver->IsActive() && iResumePending ) | 
|         |    302         { | 
|         |    303         iResumePending = EFalse; | 
|         |    304         iNotifyObserver->Activate(); | 
|         |    305         iSemaphore.Signal(); // Resume thread stepping | 
|         |    306         } | 
|         |    307     } | 
|         |    308  | 
|         |    309 // ---------------------------------------------------------------------------- | 
|         |    310 // CFileManagerThreadWrapper::IsThreadStarted() | 
|         |    311 // | 
|         |    312 // ---------------------------------------------------------------------------- | 
|         |    313 TBool CFileManagerThreadWrapper::IsThreadStarted() const | 
|         |    314     { | 
|         |    315     return IsActive(); | 
|         |    316     } | 
|         |    317  | 
|         |    318 // ---------------------------------------------------------------------------- | 
|         |    319 // CFileManagerThreadWrapper::CNotifyObserver::CNotifyObserver() | 
|         |    320 // | 
|         |    321 // ---------------------------------------------------------------------------- | 
|         |    322 CFileManagerThreadWrapper::CNotifyObserver::CNotifyObserver( | 
|         |    323     CFileManagerThreadWrapper& aWrapper ) : | 
|         |    324         CActive( CActive::EPriorityStandard ), | 
|         |    325         iWrapper( aWrapper ) | 
|         |    326     { | 
|         |    327     } | 
|         |    328  | 
|         |    329 // ---------------------------------------------------------------------------- | 
|         |    330 // CFileManagerThreadWrapper::CNotifyObserver::NewL() | 
|         |    331 // | 
|         |    332 // ---------------------------------------------------------------------------- | 
|         |    333 CFileManagerThreadWrapper::CNotifyObserver* | 
|         |    334     CFileManagerThreadWrapper::CNotifyObserver::NewL( | 
|         |    335         CFileManagerThreadWrapper& aWrapper ) | 
|         |    336     { | 
|         |    337     CNotifyObserver* self = new (ELeave) CNotifyObserver( aWrapper ); | 
|         |    338     CActiveScheduler::Add( self ); | 
|         |    339     return self; | 
|         |    340     } | 
|         |    341  | 
|         |    342 // ---------------------------------------------------------------------------- | 
|         |    343 // CFileManagerThreadWrapper::CNotifyObserver::~CNotifyObserver() | 
|         |    344 // | 
|         |    345 // ---------------------------------------------------------------------------- | 
|         |    346 CFileManagerThreadWrapper::CNotifyObserver::~CNotifyObserver() | 
|         |    347     { | 
|         |    348     Cancel(); | 
|         |    349     } | 
|         |    350  | 
|         |    351 // ---------------------------------------------------------------------------- | 
|         |    352 // CFileManagerThreadWrapper::CNotifyObserver::RunL() | 
|         |    353 // | 
|         |    354 // ---------------------------------------------------------------------------- | 
|         |    355 void CFileManagerThreadWrapper::CNotifyObserver::RunL() | 
|         |    356     { | 
|         |    357     iWrapper.DoNotifyL( iStatus.Int() ); | 
|         |    358     } | 
|         |    359  | 
|         |    360 // ---------------------------------------------------------------------------- | 
|         |    361 // CFileManagerThreadWrapper::CNotifyObserver::RunError() | 
|         |    362 // | 
|         |    363 // ---------------------------------------------------------------------------- | 
|         |    364 TInt CFileManagerThreadWrapper::CNotifyObserver::RunError( TInt aErr ) | 
|         |    365     { | 
|         |    366     return iWrapper.RunError( aErr ); | 
|         |    367     } | 
|         |    368  | 
|         |    369 // ---------------------------------------------------------------------------- | 
|         |    370 // CFileManagerThreadWrapper::CNotifyObserver::DoCancel() | 
|         |    371 // | 
|         |    372 // ---------------------------------------------------------------------------- | 
|         |    373 void CFileManagerThreadWrapper::CNotifyObserver::DoCancel() | 
|         |    374     { | 
|         |    375     // Just complete status immediately since | 
|         |    376     // background thread does not complete status anymore | 
|         |    377     TRequestStatus* status = &iStatus; | 
|         |    378     User::RequestComplete( status, KErrCancel ); | 
|         |    379     } | 
|         |    380  | 
|         |    381 // ---------------------------------------------------------------------------- | 
|         |    382 // CFileManagerThreadWrapper::CNotifyObserver::Activate() | 
|         |    383 // | 
|         |    384 // ---------------------------------------------------------------------------- | 
|         |    385 void CFileManagerThreadWrapper::CNotifyObserver::Activate() | 
|         |    386     { | 
|         |    387     if ( !IsActive() ) | 
|         |    388         { | 
|         |    389         iStatus = KRequestPending; | 
|         |    390         SetActive(); | 
|         |    391         } | 
|         |    392     } | 
|         |    393  | 
|         |    394 // ---------------------------------------------------------------------------- | 
|         |    395 // CFileManagerThreadWrapper::CNotifyObserver::Complete() | 
|         |    396 // | 
|         |    397 // ---------------------------------------------------------------------------- | 
|         |    398 void CFileManagerThreadWrapper::CNotifyObserver::Complete( | 
|         |    399     RThread& aThread, TInt aResult ) | 
|         |    400     { | 
|         |    401     if ( IsActive() ) | 
|         |    402         { | 
|         |    403         TRequestStatus* status = &iStatus; | 
|         |    404         aThread.RequestComplete( status, aResult ); | 
|         |    405         } | 
|         |    406     } | 
|         |    407  | 
|         |    408 // End of File   |