
Бывалый

Профиль
Группа: Участник
Сообщений: 165
Регистрация: 9.1.2007
Где: Россия, Москва
Репутация: нет Всего: нет
|
Прототип Код | namespace Z { namespace Basis { class Thread;
typedef unsigned long (*thread_action)(void *Argument, Thread *Parent); // ...........................................................> Функция вызываемая потоком
struct thread_argument { thread_action Action; // .........................................................................................................> Указатель функции для вызова потоком void *Argument; // ...............................................................................................................> Аргумент для функции вызываемой потоком };
class Thread { public:
Thread(thread_action Action, void *Argument, unsigned long *Return); // ..........................................................> Конструктор /* Конструктор объекта потока принимающий в качестве аргументов указатель на функцию подвызова потока, указатель на аргументы * передаваемые потоку (пользовательской функции - подвызову потока). Параметр Return является указателем на вшенюю переменную * для возвращаемого значения потока. В качестве данного аргумента можно указать NULL. В любом из случаев, объект потока вернет * код выхода потока при вызове GetExitCode если поток завершен. */
~Thread(); // ....................................................................................................................> Деструктор /* Деструктор не завершает поток принудительно, он ожидает завершение потока. Если поток не была запущен, то деструктор завершает * поток без его выполнения подвызова (рекомендуемым способом, без применения TerminateThread) */
unsigned int Start(); // .........................................................................................................> Запустить поток /* Метод размораживает поток в случае вызова после конструктора. Если вызов повторный, проверяется активность потока. Если поток * завершен, производится сброс объекта и повторный вызов потока. Если поток еще выполняется, данный вызов игнорируется */
bool Pause(unsigned int Delay); // ...............................................................................................> Заморозить поток /* Функция замораживает поток. В случае если Delay равен нулю, поток замораживается до вызова Start. Если Delay больше нуля, то * поток замораживается на периуд указанный в Delay. */
bool Stop(unsigned int Wait); // .................................................................................................> Остановить поток /* Принудительное завершение потока. Параметр Wait Указывает количество десятых секунды ожидания. Если значение Wait равное нулю, * то поток завершается вызовом TerminateThread с кодом выхода 0. Если Wait больше нуля, то функция ожидает заданный периуд в * десятых долях секунды, и если поток не завершился, вызывается TerminateThread с кодом выхода равным 0 */
bool Wait(); // ..................................................................................................................> Ожидание завершения потока /* Проверяет активность объекта. (!) Может привести к зависанию главного потока в случае если не был произведен вызов Start */
unsigned long GetID(); // ........................................................................................................> Взять идентификатор потока /* Возвращает идентификатор потока */
void *GetHandle(); // ............................................................................................................> Взять дескриптор потока /* Возвращает дескриптор (адрес объекта ядра) потока */
unsigned long GetExitCode(); // ..................................................................................................> Взять код возврата потока /* Возвращает код выхода потока. Если поток не завершен, возвращается значение 0. Для проверки завершенности потока можно * использоваться функцию Wait, но при условии предварительного вызова Start */
private: thread_argument _ThreadArgument; // ..............................................................................................> Структура аргументов для потока unsigned long *_Return; // .......................................................................................................> Указатель на значение возвращаемое потоком unsigned long _ThreadExitCode; // ................................................................................................> Код возврата потока
bool _ThreadStartControl; // .....................................................................................................> Флаг контроля запуска потока bool _ThreadCompleted; // ........................................................................................................> Флаг завершенности потока
unsigned long _ThreadID; // ......................................................................................................> Идентификатор потока void *_ThreadHandle; // ..........................................................................................................> Дескриптор потока
static unsigned long __stdcall _ThreadFunction(void *Argument); // ...............................................................> Функция потока }; } }
|
Реализация Функция _Format это аналог sprintf тока возвращающий string, вместо аргумента указателя результирующей строки str Функция IternalShellError это функция которая выводит ошибку либо в консоль, либо в MessageBox и завершает приложение ExitProccess Оповещение об ошибке на скорую руку  Код | Z::Basis::Thread::Thread(thread_action Action, void *Argument, unsigned long *Return) { _ThreadArgument.Action = Action; // ......................................................................................................> Присвоения указателя пользовательской функции _ThreadArgument.Argument = Argument; // ..................................................................................................> Присвоение указателя на аргументы if (Return == NULL) { // .................................................................................................................> Проверка указателя на внешнюю переменную кода выхода -> _Return = &_ThreadExitCode; // .......................................................................................................> Берется указатель переменной объекта _ThreadExitCode = 0; // ..............................................................................................................> Оонуление переменной кода возврата объекта } else { _Return = Return; // .................................................................................................................> Присваивается указатель на внешнюю переменную *_Return = 0; // .....................................................................................................................> Обнуление внешней переменной кода возврата }
_ThreadStartControl = false; // ..........................................................................................................> Флаг контроля запуска потока _ThreadCompleted = false; // .............................................................................................................> Флаг завершенности потока
_ThreadID = 0; // ........................................................................................................................> Обнуление идентификатора потока _ThreadHandle = CreateThread(NULL, 0, &_ThreadFunction, this, CREATE_SUSPENDED, &_ThreadID); // ..........................................> Создание потока if (_ThreadHandle == NULL) { // ..........................................................................................................> Дескриптор потока пуст - поток не создан Z::InternalShellError("Failed to create thread"); } }
Z::Basis::Thread::~Thread() { if (!_ThreadStartControl) { // ...........................................................................................................> Проверка флага контроля запуска потока -> _ThreadStartControl = true; // .......................................................................................................> Поток неактивен - необходим запуск с завершением Start(); // ..........................................................................................................................> Запуск а завершением }
bool ThreadWork = true; // ...............................................................................................................> Флаг активности потока while (ThreadWork) { // ..................................................................................................................> Цикл проверки активности потока -> unsigned long WaitResult = WaitForSingleObject(_ThreadHandle, 100); // ...............................................................> Проверка занятости объекта if (WaitResult == WAIT_OBJECT_0) // ..................................................................................................> Поток завершился -> ThreadWork = false; // ...........................................................................................................> Выход из цикла проверки активности else if (WaitResult == WAIT_FAILED) // ...............................................................................................> Ошибка проверки активности потока Z::InternalShellError(_Format("Failed to wait thread %lu", GetLastError()).c_str()); // ..........................................> Оповещение об ошибке } if (CloseHandle(_ThreadHandle) == 0) // ..................................................................................................> Попытка закрыть дескриптор потока Z::InternalShellError(_Format("Failed to close thread handle %lu", GetLastError()).c_str()); GetExitCode(); // ........................................................................................................................> Взятие кода возврата потока }
unsigned int Z::Basis::Thread::Start() { if (_ThreadCompleted) { // ...............................................................................................................> Проверка завершенности потока -> _ThreadStartControl = false; // ......................................................................................................> Сброс флага контроля запуска потока _ThreadCompleted = false; // .........................................................................................................> Сброс флага завершенности потока _ThreadID = 0; // ....................................................................................................................> Обнуление идентификатора потока _ThreadHandle = CreateThread(NULL, 0, &_ThreadFunction, this, 0, &_ThreadID); // .....................................................> Создание и запуск потока return 2; // .........................................................................................................................> Новый поток создан и запущен на выполнение }
unsigned long WaitResult = WaitForSingleObject(_ThreadHandle, 0); // .....................................................................> Проверка занятости объекта if (WaitResult == WAIT_OBJECT_0) // ......................................................................................................> Поток завершился -> return 0; else if (WaitResult == WAIT_FAILED) // ...................................................................................................> Ошибка проверки активности потока Z::InternalShellError(_Format("Failed to wait thread on start %lu", GetLastError()).c_str()); // .....................................> Оповещение об ошибке
if (ResumeThread(_ThreadHandle) == -1) // ................................................................................................> Попытка разморозки потока Z::InternalShellError(_Format("Failed to resume thread %lu", GetLastError()).c_str()); // ............................................> Оповещение об ошибке return 1; }
bool Z::Basis::Thread::Pause(unsigned int Delay) { unsigned long WaitResult = WaitForSingleObject(_ThreadHandle, 0); // .....................................................................> Проверка занятости объекта if (WaitResult == WAIT_OBJECT_0) // ......................................................................................................> Поток завершился -> return false; else if (WaitResult == WAIT_FAILED) // ...................................................................................................> Ошибка проверки активности потока Z::InternalShellError(_Format("Failed to wait thread on pause %lu", GetLastError()).c_str()); // ......................................> Оповещение об ошибке
if (SuspendThread(_ThreadHandle) == -1) // ...............................................................................................> Попытка заморозки потока Z::InternalShellError(_Format("Failed to suspend thread %lu", GetLastError()).c_str()); // ...........................................> Оповещение об ошибке if (Delay > 0) { // ......................................................................................................................> Если время заморозки больше нуля -> Sleep(Delay); // .....................................................................................................................> Задержка перед разморозкой Start(); // ..........................................................................................................................> Разморозка потока } return true; }
bool Z::Basis::Thread::Stop(unsigned int Wait) { for (unsigned int Index = 0; Index < Wait; Index++) { // .................................................................................> Цикл ожидания потока -> if (WaitForSingleObject(_ThreadHandle, 100) == 0) { // ...............................................................................> Итерация цикла ожидания -> GetExitCodeThread(_ThreadHandle, _Return); // ....................................................................................> Взятие кода возврата потока return true; } } TerminateThread(_ThreadHandle, 0); // ....................................................................................................> Принудительное завершение потока GetExitCode(); // ........................................................................................................................> Взятие кода возврата потока return false; }
bool Z::Basis::Thread::Wait() { unsigned long WaitResult = WaitForSingleObject(_ThreadHandle, INFINITE); // ..............................................................> Ожидание завершения потока if (WaitResult == WAIT_OBJECT_0) // ......................................................................................................> Потока завершился return true; else if (WaitResult == WAIT_FAILED) Z::InternalShellError(_Format("Failed to wait thread %lu", GetLastError()).c_str()); // ..............................................> Оповещение об ошибке }
unsigned long Z::Basis::Thread::GetID() { return _ThreadID; }
void *Z::Basis::Thread::GetHandle() { return _ThreadHandle; }
unsigned long Z::Basis::Thread::GetExitCode() { GetExitCodeThread(_ThreadHandle, _Return); // ............................................................................................> Взятие кода возврата потока return *_Return; }
unsigned long __stdcall Z::Basis::Thread::_ThreadFunction(void* Argument) { Thread *Parent = reinterpret_cast<Thread*> (Argument); // ................................................................................> Приведение типа указателя
if (Parent->_ThreadStartControl) // ......................................................................................................> Проверка флага контроля запуска потока -> return 0; // .........................................................................................................................> Запуск отменяется - завершение потока else // ..................................................................................................................................> Запуск разрешен -> Parent->_ThreadStartControl = true; // ...............................................................................................> Отметка о произведенном запуске потока
unsigned long Return = Parent->_ThreadArgument.Action(Parent->_ThreadArgument.Argument, Parent); // ......................................> Вызов пользовательской функции потока return Return; // ........................................................................................................................> Возврат значения пользовательской функции потока }
|
Добавлено @ 20:58Там в Pause используется Sleep. Дело неблагодарное, так как заснет все, не только замораживаемый поток  Это не к чему. Может имеет смысл для онной реализации использовать поток коллектора (единственный на объект коллектора...) или ваще отнять эту возможность. В общем, это я так, для ассортимента вставил, Sleep этот. main Код | unsigned long ThreadFunction(void *Argument, Z::Basis::Thread *Parent) { string *ArgumentString = reinterpret_cast<string*>(Argument); printf("Im a ID:%lu HANDLE:%p thread with a `%s` argument and im guess return 666 value. It's there? \n", Parent->GetID(), Parent->GetHandle(), ArgumentString->c_str()); return 666; }
int main(int argc, char** argv) { system("cls"); unsigned long Ret = 0; string StringForThread("ArgString"); Z::Basis::Thread _Thread_A(&ThreadFunction, &StringForThread, NULL); Z::Basis::Thread _Thread_B(&ThreadFunction, &StringForThread, NULL); _Thread_A.Start(); _Thread_A.Wait(); printf("Ret is %lu\n", _Thread_A.GetExitCode()); if (_Thread_A.GetExitCode() == 666) printf("That's OK!"); return 0; }
|
Это сообщение отредактировал(а) NYX - 16.7.2012, 01:49
--------------------
'long long long' is too long for GC
|