fclt Logo
A thread class
Une classe thread
WinThread is a simple thread class that mimics the use of the VCL TThread class. It's an abstract base class which means you have to derive your own class from it and implement the Execute method where the main code of your thread must be.
WinThread est une classe qui implémente les threads Windows et imite le fonctionnement de la classe TThread de la VCL. C'est une classe abstraite et vous devez donc dériver votre propre classe de celle-ci et implémenter la méthode Execute.

#ifndef WINTHREAD_H
#ifndef WINTHREAD_H
#define WINTHREAD_H
//-----------------------------------------------------------------
#include <windows.h>

namespace mlLib
{

class CriticalSection
{
  private:
    CRITICAL_SECTION cs_;
  public:
    CriticalSection() {InitializeCriticalSection(&cs_);}
    ~CriticalSection() {DeleteCriticalSection(&cs_);}
    void acquire() {EnterCriticalSection(&cs_);}
    void release() {LeaveCriticalSection(&cs_);}
};

/**
 * Provide a safe way to use CriticalSection.
 * Imagine protecting data like this:
 *  CriticalSection protect;
 *  protect.acquire();
 *     //data to be protected
 *  protect.release();
 * If 'data to be protected' throws an exception, the critical
 * section will never be released. The class Lock avoid this
 * problem releasing the critical section when it goes out
 * of scope.
 */
class Lock
{
  private:
    CriticalSection &section_;
  public:
    Lock(CriticalSection &section) : section_(section)
    {
      section_.acquire();
    }
    ~Lock() {section_.release();}
};

/**
 * To use WinThread, you have to derive your own thread class
 * from WinThread and implement the Execute() method which is
 * where your thread code is executed.
 * Winthread is created in suspended mode. To run the thread,
 * call Resume().
 * The Execute() method should periodically check the state of
 * te Terminated property to know if another thread has requested
 * to terminate your thread.
 */
class WinThread
{
  private:
    HANDLE handle_;
    DWORD id_;
    bool suspended_;
    CriticalSection cs_;
    static DWORD __stdcall ThreadFunc(void* arg);
    WinThread(const WinThread&);
    WinThread& operator=(const WinThread&);
  protected:
    virtual void Execute()=0;
    bool Terminated;
  public:
    WinThread();
    virtual ~WinThread();
    bool Create();
    DWORD GetThreadId()const{return id_;}
    void Resume();
    void Suspend();
    void Terminate();
    void WaitFor(DWORD delay=INFINITE);
    bool SetPriority(int priority);
    int GetPriority();
};
//-----------------------------------------------------------------
//end namespace mlLib
#endif

#include "winthread.h"

mlLib::WinThread::WinThread():
    handle_(0),id_(0),suspended_(true),Terminated(false)
{

}

mlLib::WinThread::~WinThread()
{
  if(!Terminated && !suspended_)
  {
    Terminate();
    WaitFor();
  }    
  if(handle_)CloseHandle(handle_);
}

bool mlLib::WinThread::Create()
{
  handle_ = CreateThread(NULL,0,ThreadFunc,this,CREATE_SUSPENDED,&id_);
  if(handle_)return true;
  return false;
}

void mlLib::WinThread::Resume()
{
  if(suspended_)
  {
    Lock protect(cs_);
    if(suspended_)
    {
      ResumeThread(handle_);
      suspended_ = false;
    }
  }
}

void mlLib::WinThread::Suspend()
{
  if(!suspended_)
  {
    Lock protect(cs_);
    if(!suspended_)
    {
      SuspendThread(handle_);
      suspended_ = true;
    }
  }
}

void mlLib::WinThread::Terminate()
{
  if(!Terminated)
  {
    Lock protect(cs_);
    if(!Terminated)Terminated = true;
    Resume();
  }
}

void mlLib::WinThread::WaitFor(DWORD delay)
{
  WaitForSingleObject(handle_,delay);
}

DWORD __stdcall mlLib::WinThread::ThreadFunc(void* arg)
{
  WinThread *ptr=reinterpret_cast<WinThread*>(arg);
  if(ptr)
  {
    ptr->Execute();
    ptr->Terminated = true;
  }
  return 0;
}

bool mlLib::WinThread::SetPriority(int priority)
{
  return SetThreadPriority(handle_,priority); 
}

int mlLib::WinThread::GetPriority()
{
  return GetThreadPriority(handle_); 
}

To use this class, as the Execute() methode is declared as pure virtual, you must derive your own class from the abstract base class WinThread. Your thread code is placed in the body of your Execute() method and must check periodically if the thread is requested to terminate.
Below, a skeleton of a derived class from WinThread:
La méthode Execute() de la classe WinThread est déclarée virtuelle pure ce qui veut dire que vous devez l'implémenter dans votre classe dérivée de WinThread. Dans le corps de la fonction, vous placez le code que doit exécuter votre thread en testant régulièrement si celui-ci doit se terminer.
Ci-dessous, un squelette de classe dérivée de WinThread:

#include "winthread.h"

class MyThread : public mlLib::WinThread
{
  public:
    MyThread() : mlLib::WinThread() {}
    ~MyThread() {}
  
  private:
    void Execute();
};

void MyThread::Execute()
{
  while (!Terminated)
  {
    // put your thread code here
  }
}

To download the WinThread class, click here.
Don't forget when you compile an application using threads to add the appropriate switches and to link to the appropriate multithread version of the runtime lib file.
Pour télécharger le code de la classe WinThread, cliquez ici.
N'oubliez pas d'ajouter lors de la compilation, les switchs nécessaires et lors du link, d'inclure la version multithread des librairies.