Класс обертка для потока(Thread)
От: Gorik Россия  
Дата: 28.08.02 13:38
Оценка:
Здраствуйте, уважаемые жители RSDN.
Представляю вашему вниманию класс который разработал год назад. Он до сих пор не потерял своей актуальности, и думаю еще долго не потеряет.
Кстати переделывание старых проектов для работы через этот класс занимало минимум усилий. Но, возможно, это оттого, что я автор. Надеюсь мне все же удастся донести до общественности основные идеи.

К идее создания этого класса меня привела досадная неполноценность ряда операционных систем от одной мелкомягкой компании. Фукция TerminateThread появилась только в Win2k, да и то она убивает поток, а выделенные ресурсы так и остаются, до смерти самого процесса. Хочется чего-нибудь краткого и мощного. Это и было сделано.


// thread.h: interface for the threadable class.
//
// Design by Petrov Evgeniy with Todyshev Sergey 2001
//////////////////////////////////////////////////////////////////////

#ifndef _THREAD_INC_HEADER
#define _THREAD_INC_HEADER

/*concept:
  Испокон веков поток реализовывался одной функцие примерно следующего вида.

  UINT ThreadFunc(LPVOID pData)
  {
     ...
     Инициализация - в полном смысле этого слова
     ...
     while(need_continue)
     {
         ....
         Поток что-то делает
         ....
     }
     ...
     Завершение (всякого рода освобождение ресурсов)
     ...
     return _retval;
  }

  Естественно различные задачи требуют различной реализации, данный подход применим лишь
  для самой популярной модели.

  И, коль скоро удалось применить декомпозицию к такой сущности как Поток, то логично 
  агрегировать эти части в класс, что и сделано ниже.

  Инициализация.
  Шаг.
  Завершение.

  Имеено на эти части можно разбить любой нормальный поток. 
*/

/*
  Зачем все это нужно?
  Обычный поток недостаточно управляем. Поскольку все собрано в одной функции, нет 
  возможности манипулировать отдельными частями. Предлагаемый класс достаточно легко и
  интуитивно позволяет манипулировать потоком.
*/


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning(disable:4786)
#pragma warning(disable:4800)
#include "semaphore.h"
#include <map>
using namespace std;



// Флаги состояния потока
#define _THREAD_STATUS_UNKNOWN        0x000

#define _THREAD_STATUS_STARTED        0x001
// Поток в работе (т.е в основном цикле)
#define _THREAD_STATUS_SUSPENDED    0x002
// Поток приостановлен
#define _THREAD_STATUS_FINISHING    0x004
// Идет завершение 
#define _THREAD_STATUS_STARTING        0x008
// Идет инициализация


class cThread: public semaphore
{
public:

    // Инициализация данных, для данного экземпляра потока. 
    //Реализуется соответствующим классом потомком.
    virtual bool Init()throw(){return true;}
    // Один шаг цикла.
    virtual bool Step() throw() = 0;
    //  Завершение.
    virtual int Finish(){return 0;};

private:
    DWORD dwThreadId;
    HANDLE hThread;
    int nSleepTime;
    int nStatus;
private:
    static unsigned long __stdcall Run(void* buf);
private:
    //Блок управления флагами потока
    void Finishing(){ nStatus |= _THREAD_STATUS_FINISHING    ; }
    void Starting(){ nStatus |= _THREAD_STATUS_STARTING    ; }
    void Suspended(){ nStatus |= _THREAD_STATUS_SUSPENDED; }
    void Resumed(){ nStatus &= ~_THREAD_STATUS_SUSPENDED; }
    void Started(){ nStatus |= _THREAD_STATUS_STARTED; }
    void Stoped(){ nStatus &= ~_THREAD_STATUS_STARTED; }
public:
    cThread():dwThreadId(0),hThread(0),nStatus(_THREAD_STATUS_UNKNOWN)
    {
        SetDelay();
    }
public:

    /* Блок управления потоком*/
    // Начать поток
    virtual int Start(BOOL bSuspended=FALSE, int StackSize=0);
    // Приостановить поток
    int Suspend();
    // Разбудить поток
    virtual int Resume();
    // Остановить поток
    virtual int Stop();

public:
    int SetDelay(int dt=50){ return nSleepTime = dt; }
    int GetDelay() const {return nSleepTime;}
    int SetPriority(int prior) { return IsStarted()?SetThreadPriority(hThread,prior):THREAD_PRIORITY_ERROR_RETURN;}
    int GetPriority(int prior) const { return IsStarted()?GetThreadPriority(hThread):THREAD_PRIORITY_ERROR_RETURN;}
private:
    bool IsFinishing() const { return nStatus & _THREAD_STATUS_FINISHING; }
    bool IsStarting() const { return nStatus & _THREAD_STATUS_STARTING; }
public:
    bool IsSuspended() const { return nStatus & _THREAD_STATUS_SUSPENDED; }
    bool IsResumed() const { return !IsSuspended(); }
    bool IsStarted() const { return dwThreadId!=0&&hThread!=0&&(nStatus & _THREAD_STATUS_STARTED); }
    bool IsStoped() const { return !IsStarted(); }
};

#endif // _THREAD_INC_HEADER


А вот реализация.

// thread.cpp: implementation of the threadable class.
//
// Design by Petrov Evgeniy with Todyshev Sergey 2001
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "thread.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

unsigned long cThread::Run(void* buf)
{
    cThread * pThread = (cThread*)buf;
    if(pThread->Init())
    {
        pThread->nStatus=_THREAD_STATUS_STARTED;
        while(!pThread->IsFinishing())
        {
            if(!pThread->Step())
                break;
            Sleep(pThread->GetDelay());
        }
        pThread->Finish();
    }
    pThread->nStatus=_THREAD_STATUS_UNKNOWN;
    return 0;
}
int cThread::Start(BOOL bSuspended, int StackSize)
{
    if(IsStarted())
        return false;
    hThread=CreateThread(NULL,StackSize,Run,this,bSuspended?CREATE_SUSPENDED:0,&dwThreadId);
    if(hThread)
    {
        if(bSuspended)
        {
            Suspended();
            return true;
        }
        Starting();
        while(IsStarting())
            Sleep(70);
        return true;
    }
    else
    {
        dwThreadId = 0;
        nStatus=_THREAD_STATUS_UNKNOWN;
        return false;
    }
}
int cThread::Stop()
{
    if(IsStoped())return false;
    Resume();
    Finishing();
    while(IsStarted()&&IsFinishing())
        Sleep(70);
    nStatus = _THREAD_STATUS_UNKNOWN;
    return true;
}

int cThread::Suspend()
{
    if(IsSuspended()||IsStoped()) return false;
    if(SuspendThread(hThread)==-1)
        return false;
    Suspended();
    return true;
}
int cThread::Resume()
{
    if(IsResumed()||IsStoped()) return false;
    if(ResumeThread(hThread)==-1)
        return false;
    Resumed();
    return true;
}


Пользуйтесь.
Возможно я переоцениваю важность данной идеи. Но мне эти строки спасли много нервов.

Чтобы пользоваться достаточно пронаследоваться и реализовать соответствующие члены-функции.
Фарш невозможно провернуть назад (с)Второе начало термодинамики
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.