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

#ifndef STRUKTURYCZASU_H_
#define STRUKTURYCZASU_H_

#include <e32std.h>        // TTimeIntervalMicroSeconds32

class TCzas
{
    public:
        // Czas w mikrosekundach (1/1000000)
        TTimeIntervalMicroSeconds32 iCzas;
};

class TCzasMikrosek : public TCzas
{
    public:
        TCzasMikrosek( TInt aMikroSek ) { iCzas = aMikroSek; }
};

class TCzasMilisek : public TCzas
{
    public:
        TCzasMilisek( TInt aMiliSek ) { iCzas = aMiliSek* 1000; }
};

class TCzasSek : public TCzas
{
    public:
        TCzasSek( TInt aSek ) { iCzas = aSek * 1000000; }
};

#endif /* STRUKTURYCZASU_H_ */

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

#ifndef STOPER_H_
#define STOPER_H_

#include <e32base.h>            // CActive - nagwek z SDK
#include "StrukturyCzasu.h"        // TCzas - nagwek projektu

class MObserwerStopera
{
    public:
        virtual void CzasOdmierzonyL() = 0;
        virtual void OdmierzanieCzasuPrzerwane( TInt aBlad ) = 0;
};

class CStoper : public CActive
{
    public:        // Konstruktory dwufazowe
        static CStoper* NewL( MObserwerStopera& aObserwer );
        static CStoper* NewLC( MObserwerStopera& aObserwer );
        ~CStoper();
        
    public:
        void OdmierzCzas( TCzas aCzas );
        
    private:    // Odziedziczone z CActive
        // Implementacje wymagane
        void DoCancel();
        void RunL();
        // Implementacja opcjonalna
        TInt RunError( TInt aError );
        
    private:    // Konstruktory
        // - pierwsza faza
        CStoper( MObserwerStopera& aObserwer );
        // - druga faza
        void ConstructL();
        
    private:    // Pola
        MObserwerStopera& iObserwer;
        
        // Klasa RTimer peni rol Dostawcy Usug Asynchronicznych
        RTimer iZegar;
};

#endif /* STOPER_H_ */

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

#include "Stoper.h"

CStoper* CStoper::NewL( MObserwerStopera& aObserwer )
{
    CStoper* self = CStoper::NewLC( aObserwer );
    CleanupStack::Pop( self );
    return self;
}

CStoper* CStoper::NewLC( MObserwerStopera& aObserwer )
{
    CStoper* self = new( ELeave ) CStoper( aObserwer );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

CStoper::CStoper( MObserwerStopera& aObserwer )
// Lista inicjalizacyjna:
// 1. Obowizkowy konstruktor klasy bazowej
:CActive( EPriorityStandard )
// 2. Referencja do obiektu obserwera
,iObserwer( aObserwer )
{
    // Dodanie obiektu do listy aktywnych obiektw aktualnie
    // zainstalowanego Zarzdcy Aktywnoci
    CActiveScheduler::Add( this );
}

CStoper::~CStoper()
{
    // Przeczamy obiekt w stan nieaktywny (jeeli ju jest
    // w stanie nieaktywnym, metoda Cancel() nie wykona adnej czynnoci).
    Cancel();
    // Zwalniamy obiekt zegara.
    iZegar.Close();
}

void CStoper::ConstructL()
{
    // Inicjalizujemy obiekt zegara.
    iZegar.CreateLocal();
}

void CStoper::OdmierzCzas( TCzas aCzas )
{
    // Wywoujemy usug asynchroniczn - przekazujemy jej referencj
    // do pola iStatus aktywnego obiektu.
    iZegar.After( iStatus, aCzas.iCzas );
    // Przeczamy obiekt w stan aktywny. Obiekt od tej pory czeka na
    // wykonanie usugi asynchronicznej. Pominicie wywoania metody
    // SetActive() spowoduje, e po wykonaniu usugi Zarzdca Aktywnoci
    // nie bdzie mg odnale obiektu odpowiedzialnego za jej obsuenie
    // i wygeneruje panik EUSER-CBase 46.
    SetActive();
}

void CStoper::DoCancel()
{
    // Anulujemy usug po stronie Dostawcy Usug Asynchronicznych.
    iZegar.Cancel();
}

void CStoper::RunL()
{
    // Usuga wykonana - przekazujemy informacj do obiektu
    // obserwera.
    TInt blad = iStatus.Int();
    
    if( blad == KErrNone )
    {
        iObserwer.CzasOdmierzonyL();
    }
    else
    {
        iObserwer.OdmierzanieCzasuPrzerwane( blad );
    }
}

TInt CStoper::RunError( TInt aError )
{
    iObserwer.OdmierzanieCzasuPrzerwane( aError );
    return KErrNone;
}

// ----------------
// Uycie klasy CStoper
// ----------------
iStoper = CStoper::NewL( *this );
// Odmierz czas rwny 1 sek.
// Po opywie tego czasu wywoana zostanie metoda
// this::CzasOdmierzonyL().
iStoper->OdmierzCzas( TCzasSek( 1 ) );
