Säieluokka

empty 23.10.03 22:42

Luokka joka mahdollistaa säikeen tekemisen

 Tekstiversio  Arvo: 0 (1 ääntä)  Äänestä: +  -
header:

#include <windows.h>

/*
*This class must be inherited in order to use it. Method run is pure virtual and
*must therefore be overridden.
*
*@author Mika
*/

class ThreadClass
{
public:
        ThreadClass();
        ~ThreadClass();

        /**
        *By calling this method it starts a new thread
        *@return handle for thread
        */

        HANDLE start( void );

        /**
        *This is the pure virtual method called while thread is running.
        */

        virtual int run( void ) = 0;

private:
        static int runnable( void* );

};

source:

#include "ThreadClass.hpp"

/**
*We need this struct to solve casting problem.
*If this pointer were used it would cause following problem.
*Class that inherits ThreadClass would
*have to be converted that class to (void *) and pass it on to runnable.
*Runnable would reconvert it to ThreadClass. Standard only allows conversion to (class*)
*to (void*) and back. Further converions would result randomly behaviour.
*/

struct workAround
{
        ThreadClass* thisThread;
};

ThreadClass::ThreadClass(){}
ThreadClass::~ThreadClass(){}

HANDLE ThreadClass::start()
{
        workAround* wA  = new workAround;
        wA->thisThread  = this;
        return ::CreateThread (NULL, 0, (unsigned long (__stdcall *)(void *))this->runnable,
                                                  (void *)wA, 0, NULL);
}       

int ThreadClass::runnable (void* pThis)
{
        workAround* wA  = (workAround*)pThis;
        //this will call the appropriate method, as run is a pure virtual method
        ThreadClass* thread = wA->thisThread;
        delete wA;
        return thread->run();
}

Esimerkki luokan perimisestä:
 header:
#include "ThreadClass.hpp"

class RunableClass : public ThreadClass
{
public:
        RunableClass( char teksti[], long lMilliseconds );
        ~RunableClass();

        int run( void );
        bool isRunning( void );
        void stop( void );

private:
        char m_teksti[20];
        bool m_bRunning;
        long m_lMilliseconds;
};

source:
#include <iostream.h>
#include "RunableClass.hpp"

RunableClass::RunableClass( char teksti[], long lMilliseconds )
{
        strcpy( m_teksti, teksti );
        this->m_bRunning = true;
        this->m_lMilliseconds = lMilliseconds;
}
RunableClass::~RunableClass(){}

bool RunableClass::isRunning( void ){ return this->m_bRunning; }
void RunableClass::stop( void ){ this->m_bRunning = false; }

int RunableClass::run( void )
{
        while( this->m_bRunning )
        {
                cout << this->m_teksti << endl;
                Sleep( this->m_lMilliseconds );
        }
        return 0;
}

Ja lopuksi esimerkki main. Sitä ennen pyyhkäisen hikeä... phuuh!

#include "RunableClass.hpp"

void main( void )
{
        RunableClass ajo1( "teksti1", 1000 );
        RunableClass ajo2( "teksti2", 500 );

        ajo1.start();
        ajo2.start();

        Sleep( 2000 );

        ajo2.stop();

        Sleep( 3000 );

        ajo1.stop();
}

Elikkäs näin. Kommentit on tervetulleita. Ainakin itselläni tuo luokka pelasi ok.
Tuo säieluokka vois olla peritty yksityiseksikin. Ja sitten esimerkkiluokalla vois olla joku oma käynnistämis metodi
joka kutsuis sitten tuota start:a.
Nythän tuo minun esimerkkiluokka laittaa m_bIsRunning = true; jo konstruktorissa vaikka ei todellisuudessa käynnistä säiettä.
Tästä seuraa se, että esimerkkiluokan tekemisen jälkeen kutsuttaissa isRunning() metodia vastaus on true vaikka todellisuudessa ei näin ole ennen kuin on ajettu start();
Huomioikaa tämä sitten jos sovellatte! :)

empty 22:44 23.10.03 
dune