/*
 * MonitorWatku.h
 *
 * Autor: Pawe Gala
 */

#ifndef MONITORWATKU_H_
#define MONITORWATKU_H_

#include <e32base.h>    // CActive


class MObserwatorWatku
{
    public:
        virtual void PierwszaFazaWykonana( TInt aBlad ) = 0;
        virtual void WykonanieWatkuZakonczone( TInt aWynik ) = 0;
};

class CMonitorWatku : public CActive
{
    public:        // Konstruktory dwufazowe i destruktor
        static CMonitorWatku* NewL( MObserwatorWatku& aObserwatorWatku );
        static CMonitorWatku* NewLC( MObserwatorWatku& aObserwatorWatku );
        
        ~CMonitorWatku();
        
    public:
        void MonitorujWatek( RThread& aWatek );
        void MonitorStop();
        
    private:    // Enumerator
        enum TStanMonitora
        {
            EBezczynny,
            ECzekanieNaPunktUstalony,
            ECzekanieNaZakonczenieWatku
        };
        
    private:    // Odziedziczone z klasy CActive
        void DoCancel();
        void RunL();
        
    private:    // Konstruktory pierwszej i drugiej fazy
        CMonitorWatku( MObserwatorWatku& aObserwatorWatku );
        void ConstructL();
        
    private:    // Pola
        MObserwatorWatku& iObserwatorWatku;
        
        TStanMonitora iStan;
        RThread* iMonitorowanyWatek;
};

#endif /* MONITORWATKU_H_ */

/*
 * MonitorWatku.cpp
 *
 * Autor: Pawe Gala
 */

#include "MonitorWatku.h"

CMonitorWatku* CMonitorWatku::NewL( MObserwatorWatku& aObserwatorWatku )
{
    CMonitorWatku* self = CMonitorWatku::NewLC( aObserwatorWatku );
    CleanupStack::Pop( self );
    return self;
}

CMonitorWatku* CMonitorWatku::NewLC( MObserwatorWatku& aObserwatorWatku )
{
    CMonitorWatku* self = new( ELeave ) CMonitorWatku( aObserwatorWatku );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

CMonitorWatku::CMonitorWatku( MObserwatorWatku& aObserwatorWatku )
:CActive( EPriorityStandard )
,iObserwatorWatku( aObserwatorWatku )
{
    CActiveScheduler::Add( this );
}

CMonitorWatku::~CMonitorWatku()
{
    MonitorStop();
}

void CMonitorWatku::ConstructL()
{
}

void CMonitorWatku::MonitorujWatek( RThread& aWatek )
{
    iMonitorowanyWatek = &aWatek;
    Cancel();
    
    iMonitorowanyWatek->Rendezvous( iStatus );
    SetActive();
    
    iStan = ECzekanieNaPunktUstalony;
}

void CMonitorWatku::MonitorStop()
{
    Cancel();
    iStan = EBezczynny;
}

void CMonitorWatku::DoCancel()
{
    switch( iStan )
    {
        case ECzekanieNaPunktUstalony:
        {
            iMonitorowanyWatek->RendezvousCancel( iStatus );
        }
        break;
        
        case ECzekanieNaZakonczenieWatku:
        {
            iMonitorowanyWatek->LogonCancel( iStatus );
        }
        break;
    }
}

void CMonitorWatku::RunL()
{
    switch( iStan )
    {
        case ECzekanieNaPunktUstalony:
        {
            // Rozpoczynamy czekanie na zakoczenie wtku.
            iMonitorowanyWatek->Logon( iStatus );
            SetActive();
            
            iStan = ECzekanieNaZakonczenieWatku;
            
            iObserwatorWatku.PierwszaFazaWykonana( iStatus.Int() );
        }
        break;
        
        case ECzekanieNaZakonczenieWatku:
        {
            iStan = EBezczynny;
            iObserwatorWatku.WykonanieWatkuZakonczone( iStatus.Int() );
        }
        break;
    }
}

// ----------------
// Uycie klasy CMonitorWatku
// ----------------

// Tworzymy monitor wtku.
iMonitorWatku = CMonitorWatku::NewL( *this );

// Tworzymy wtek.
_LIT( KNazwaWatku, "DrugiWatekProcesu" );
TInt blad = iWatek.Create( KNazwaWatku, 
                FunkcjaWatku,
                KDefaultStackSize,
                NULL,    // aHeap = NULL, uywamy sterty wtku gwnego.
                NULL );    // Nie przekazujemy do wtku parametrw.

if( blad == KErrNone )
{
    // Rozpoczynamy obserwowanie wtku.
    iMonitorWatku->MonitorujWatek( iWatek );
    iWatek.Resume();
}
else
{
    // Obsuga bdu
}
