webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp
changeset 10 a359256acfc6
parent 0 dd21522fd290
child 15 60c5402cb945
--- a/webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp	Fri Jul 03 15:54:40 2009 +0100
+++ b/webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp	Thu Aug 27 07:44:59 2009 +0300
@@ -40,6 +40,7 @@
         TInt iMaskHandle;
 };
 
+enum DecoderState {ENewDecodeRequest, EDecodeInProgress, EDecoderIdle};
 class CSynDecoder : public CActive
     {
     public:  // Constructors and destructor
@@ -47,25 +48,35 @@
         virtual ~CSynDecoder();
 
     public:
-        TInt Open(BmElem* aElem);
+        void Open(const TDesC8& aData, TRequestStatus *status);
+        void Lock() { iDecoderLock.Wait(); }
+        void Release() { iDecoderLock.Signal(); }
 
     private: // From base class CActive
         void DoCancel();
         void RunL();
         TInt RunError( TInt aError );
         void SignalParent( TInt aError );
+        void StartDecodeL();        
+        void SetIdle();
         
     private: // Private constructors
         CSynDecoder();
-        void ConstructL() {}
+        void ConstructL();
 
     private: // Data
-        BmElem* iElem; // not owned
-        CImageDecoder* iDecoder; // owned
-        CMaskedBitmap* iBitmap; // owned
+        BmElem iElem;
+        CImageDecoder* iDecoder;
+        CMaskedBitmap* iBitmap;
+        RFastLock iDecoderLock;
+        DecoderState iDecodeState;
+        RThread syncThread;
+
+friend class CSynDecodeThread;        
     };
 
 // FORWARD DECLARATIONS
+CSynDecoder *CSynDecodeThread::iSyncDecoder = NULL;
 
 // ============================= LOCAL FUNCTIONS ===============================
 
@@ -80,6 +91,12 @@
     CActiveScheduler::Add( this );
     }
 
+void CSynDecoder::ConstructL()
+{
+    User::LeaveIfError(iDecoderLock.CreateLocal());
+    SetIdle();
+}
+
 CSynDecoder* CSynDecoder::NewL()
     {
     CSynDecoder* self = new (ELeave) CSynDecoder();
@@ -94,46 +111,67 @@
     Cancel();
     delete iDecoder;
     delete iBitmap;
+    iDecoderLock.Close();
     }
 
 // -----------------------------------------------------------------------------
-// OpenL
+// Decode - Decode request submitted from client thread
 // -----------------------------------------------------------------------------
-TInt CSynDecoder::Open(BmElem* aElem)
+void CSynDecoder::Open(const TDesC8& aData, TRequestStatus *status)
+{
+    iElem.iRequestStatus = status;
+    iElem.iData.Set(aData); 
+    iElem.iParentThreadId = RThread().Id();
+    iElem.iBitmapHandle = 0;
+    iElem.iMaskHandle = 0;    
+    iDecodeState = ENewDecodeRequest;
+}
+
+void CSynDecoder::SetIdle()
 {
-    iElem = aElem;
-    // reset decoder
-    TRAPD( err, 
-        iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem->iData);
-        iBitmap = CMaskedBitmap::NewL();
-        );
-    if( err != KErrNone )
-        return err;
+    iDecodeState = EDecoderIdle;
+    if(!IsActive()) {
+        iStatus = KRequestPending;
+        SetActive();
+    }
+}
 
+void CSynDecoder::StartDecodeL()
+{
+    if(iDecoder) {
+        delete iDecoder;
+        iDecoder = NULL;
+    }
+    if(iBitmap) {
+        delete iBitmap;
+        iBitmap = NULL;
+    }
+    
+    iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem.iData);
+    iBitmap = CMaskedBitmap::NewL();
+    
     TFrameInfo frameInfo = iDecoder->FrameInfo( 0 );
-
+    TInt err = KErrNone;
     if( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) {
         TDisplayMode maskmode = (frameInfo.iFlags & TFrameInfo::EAlphaChannel) ? EGray256 : EGray2;
-
         err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K, maskmode );
     }
     else
         err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K );
-    //
-    if( err != KErrNone )
-        return err;
-   // start decoding
+    User::LeaveIfError(err);
+    
+    // start decoding
     CFbsBitmap& dstBitmap = iBitmap->BitmapModifyable();
-    CFbsBitmap& dstMask = iBitmap->MaskModifyable();
-
+    CFbsBitmap& dstMask = iBitmap->MaskModifyable();    
     if( ( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) && dstMask.Handle() )
         iDecoder->Convert( &iStatus, dstBitmap, dstMask, 0 );
     else {
         dstMask.Reset();
         iDecoder->Convert( &iStatus, dstBitmap, 0 );
     }
+    
+    iDecodeState = EDecodeInProgress;
     SetActive();
-    return KErrNone;
 }
 
 // -----------------------------------------------------------------------------
@@ -143,25 +181,31 @@
 {
     iDecoder->Cancel();
     SignalParent( KErrCancel );
+    SetIdle();
 }
 
 // -----------------------------------------------------------------------------
 // CSynDecoder::RunL
 // -----------------------------------------------------------------------------
 void CSynDecoder::RunL()
-{
-    SignalParent( iStatus.Int() );
-
-    if( iStatus.Int() == KErrNone ) {
-        iElem->iBitmapHandle = iBitmap->Bitmap().Handle();
-        iElem->iMaskHandle = iBitmap->Mask().Handle();
-
-        RThread self;
-        self.Suspend(); 
-        self.Close();
-        // destroy
-        CActiveScheduler::Stop();
-    }
+{    
+    switch(iDecodeState)
+    {
+    case ENewDecodeRequest:
+        StartDecodeL(); // start async decode
+        break;
+    case EDecodeInProgress:
+        if( iStatus.Int() == KErrNone ) {
+            iElem.iBitmapHandle = iBitmap->Bitmap().Handle();
+            iElem.iMaskHandle = iBitmap->Mask().Handle();        
+        }
+        
+        SignalParent(iStatus.Int());
+        SetIdle();
+        break;
+    default:
+        SetIdle();
+    }        
 }
 
 // -----------------------------------------------------------------------------
@@ -169,7 +213,8 @@
 // -----------------------------------------------------------------------------
 TInt CSynDecoder::RunError(TInt aError)
 {
-    SignalParent( aError );
+    SignalParent(aError);
+    SetIdle();
     return KErrNone;
 }
 
@@ -179,13 +224,11 @@
 void CSynDecoder::SignalParent(TInt aError)
 {
     RThread parent;
-    parent.Open(iElem->iParentThreadId);
-    parent.RequestComplete(iElem->iRequestStatus, aError );
-    parent.Close();            
+    parent.Open(iElem.iParentThreadId);
+    parent.RequestComplete(iElem.iRequestStatus, aError );
+    parent.Close();
+}
 
-    if (aError != KErrNone)
-        CActiveScheduler::Stop();
-}
 
 CSynDecodeThread* CSynDecodeThread::NewL()
 {
@@ -201,46 +244,45 @@
 }
 
 CSynDecodeThread::~CSynDecodeThread()
-{   	
-	if(iUp) {
-		iDecoderThread.Resume();
-		iDecoderThread.Kill(KErrNone);  
-		iDecoderThread.Close();  
-	}
-	delete iElem;
+{
+    CActiveScheduler::Stop(); 
+	iDecoderThread.Close();
+}
+
+void CSynDecodeThread::ConstructL()
+{   
+    _LIT(KThreadName, "ImgDecoder");
+    User::LeaveIfError(iDecoderThread.Create(KThreadName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, NULL));
+    iDecoderThread.SetPriority(EPriorityMore);
+    TRequestStatus status = KRequestPending;
+    iDecoderThread.Rendezvous(status);
+    iDecoderThread.Resume();
+    User::WaitForRequest(status);
+    User::LeaveIfError(status.Int());
 }
 
 
-void CSynDecodeThread::ConstructL()
+TInt CSynDecodeThread::Decode(const TDesC8& aData)
 {
-}
-
-TInt CSynDecodeThread::Decode(const TDesC8& aData, TRequestStatus* aRequestStatus)
-{
-	iElem = new (ELeave) BmElem;
-	iElem->iData.Set( aData );
-	iElem->iParentThreadId = RThread().Id();
-	iElem->iRequestStatus = aRequestStatus;
+    iSyncDecoder->Lock();
+    
+    //notify decoder thread about new request
+    TRequestStatus status = KRequestPending;
+    iSyncDecoder->Open(aData, &status);
+    TRequestStatus *ps = &(iSyncDecoder->iStatus);
+    iDecoderThread.RequestComplete(ps, KErrNone);
 
-    TBuf<20> randName;
-	TTime t;
-	t.HomeTime();
-	randName.Num( I64INT(t.Int64()) );
+    //wait for decode complete
+    User::WaitForRequest(status);    
     
-	TInt err = iDecoderThread.Create(randName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, iElem);
-    if (err==KErrNone) {
-		iUp = ETrue;
-        iDecoderThread.SetPriority(EPriorityMore);
-        *aRequestStatus = KRequestPending;
-        iDecoderThread.Resume(); 
-    }
-    return err;
+    iSyncDecoder->Release();
+    return status.Int();    
 }
 
 void CSynDecodeThread::Handle(TInt& aBitmapHandle, TInt& aMaskHandle)
 {
-    aBitmapHandle = iElem->iBitmapHandle;
-    aMaskHandle = iElem->iMaskHandle;    
+    aBitmapHandle = iSyncDecoder->iElem.iBitmapHandle;
+    aMaskHandle = iSyncDecoder->iElem.iMaskHandle;    
 }
 
 TInt CSynDecodeThread::ScaleInThread(TAny *aPtr)
@@ -248,26 +290,23 @@
     CTrapCleanup* cleanup = CTrapCleanup::New();
     CActiveScheduler* as = new CActiveScheduler;
     CActiveScheduler::Install(as);  
-
-    CSynDecoder* decoder = NULL;         
-
     RFbsSession fbs;
     fbs.Connect();
 
-    BmElem* elem = (BmElem*)aPtr;
-    TRAPD(err, decoder = CSynDecoder::NewL());
-
-    if (err == KErrNone && (err = decoder->Open(elem))== KErrNone )
-        CActiveScheduler::Start();              
-    else {    
-        RThread parent;
-        parent.Open(elem->iParentThreadId);
-        parent.RequestComplete(elem->iRequestStatus, err);
-        parent.Close();            
+    // start event loop
+    TRAPD(err, iSyncDecoder = CSynDecoder::NewL());
+    if (err == KErrNone) {
+        // wait for decode request from client threads
+        RThread().Rendezvous(KErrNone);
+        CActiveScheduler::Start();
     }
-
+    else {
+        RThread().Rendezvous(err);
+    }
+    
+    // thread shutdown 
     delete as;
-    delete decoder; 
+    delete iSyncDecoder; 
     delete cleanup; 
     fbs.Disconnect();       
     return err;