From 83fc39219825532fbbbaa6a6af2942e82f350845 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 1 Feb 2012 12:25:26 +0000 Subject: new cIsThread object for thread encapsulation git-svn-id: http://mc-server.googlecode.com/svn/trunk@214 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cIsThread.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ source/cIsThread.h | 77 +++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 source/cIsThread.cpp create mode 100644 source/cIsThread.h (limited to 'source') diff --git a/source/cIsThread.cpp b/source/cIsThread.cpp new file mode 100644 index 000000000..cee4d4477 --- /dev/null +++ b/source/cIsThread.cpp @@ -0,0 +1,148 @@ + +// cIsThread.cpp + +// Implements the cIsThread class representing an OS-independent wrapper for a class that implements a thread. +// This class will eventually suupersede the old cThread class + +#include "Globals.h" + +#include "cIsThread.h" + + + + + +// When in MSVC, the debugger provides "thread naming" by catching special exceptions. Interface here: +#ifdef _MSC_VER +// +// Usage: SetThreadName (-1, "MainThread"); +// + +static void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName) +{ + struct + { + DWORD dwType; // must be 0x1000 + LPCSTR szName; // pointer to name (in user addr space) + DWORD dwThreadID; // thread ID (-1=caller thread) + DWORD dwFlags; // reserved for future use, must be zero + } info; + + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try + { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info); + } + __except(EXCEPTION_CONTINUE_EXECUTION) + { + } +} +#endif // _MSC_VER + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cIsThread: + +cIsThread::cIsThread(const AString & iThreadName) : + mThreadName(iThreadName), + mShouldTerminate(false), + #ifdef _WIN32 + mHandle(NULL) + #else // _WIN32 + mHasStarted(false) + #endif // else _WIN32 +{ +} + + + + + +cIsThread::~cIsThread() +{ + Wait(); +} + + + + + +bool cIsThread::Start(void) +{ + #ifdef _WIN32 + assert(mHandle == NULL); // Has already started one thread? + + // Create the thread suspended, so that the mHandle variable is valid in the thread procedure + DWORD ThreadID = 0; + HANDLE mHandle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &ThreadID); + if (mHandle == NULL) + { + LOGERROR("ERROR: Could not create thread \"%s\", GLE = %d!", mThreadName.c_str(), GetLastError()); + return false; + } + ResumeThread(mHandle); + + #if defined(_DEBUG) && defined(_MSC_VER) + // Thread naming is available only in MSVC + if (!mThreadName.empty()) + { + SetThreadName(ThreadID, mThreadName.c_str()); + } + #endif // _DEBUG and _MSC_VER + + #else // _WIN32 + assert(!mHasStarted); + + if (pthread_create(&mHandle, NULL, thrExecute, this)) + { + LOGERROR("ERROR: Could not create thread \"%s\", !", mThreadName.c_str()); + return false; + } + #endif // else _WIN32 + + return true; +} + + + + + +bool cIsThread::Wait(void) +{ + #ifdef _WIN32 + + if (mHandle == NULL) + { + return true; + } + LOG("Waiting for thread \"%s\" to terminate.", mThreadName.c_str()); + int res = WaitForSingleObject(mHandle, INFINITE); + mHandle = NULL; + LOG("Thread \"%s\" %s terminated, GLE = %d", mThreadName.c_str(), (res == WAIT_OBJECT_0) ? "" : "not", GetLastError()); + return (res == WAIT_OBJECT_0); + + #else // _WIN32 + + if (!mHasStarted) + { + return true; + } + LOG("Waiting for thread \"%s\" to terminate.", mThreadName.c_str()); + int res = pthread_join(mHandle, NULL); + mHasStarted = false; + LOG("Thread \"%s\" %s terminated, errno = %d", mThreadName.c_str(), (res == 0) ? "" : "not", errno); + return (res == 0); + + #endif // else _WIN32 +} + + + + diff --git a/source/cIsThread.h b/source/cIsThread.h new file mode 100644 index 000000000..f46d7f065 --- /dev/null +++ b/source/cIsThread.h @@ -0,0 +1,77 @@ + +// cIsThread.h + +// Interfaces to the cIsThread class representing an OS-independent wrapper for a class that implements a thread. +// This class will eventually suupersede the old cThread class + +/* +Usage: +To have a new thread, declare a class descending from cIsClass. +Then override its Execute() method to provide your thread processing. +In the descending class' constructor call the Start() method to start the thread once you're finished with initialization. +*/ + + + + + +#pragma once +#ifndef CISTHREAD_H_INCLUDED +#define CISTHREAD_H_INCLUDED + + + + + +class cIsThread +{ +protected: + virtual void Execute(void) = 0; // This function is called in the new thread's context + + volatile bool mShouldTerminate; // The overriden Execute() method should check this periodically and terminate if this is true + +public: + cIsThread(const AString & iThreadName); + ~cIsThread(); + + bool Start(void); // Starts the thread + bool Wait(void); // Waits for the thread to finish + +private: + AString mThreadName; + cEvent mEvent; // This event is set when the thread begins executing + + #ifdef _WIN32 + + HANDLE mHandle; + + static DWORD_PTR __stdcall thrExecute(LPVOID iParam) + { + ((cIsThread *)iParam)->Execute(); + return 0; + } + + #else // _WIN32 + + pthread_t mHandle; + bool mHasStarted; + + static void * thrExecute(void * iParam) + { + ((cIsThread *)iParam)->Execute(); + return NULL; + } + + #endif // else _WIN32 + +} ; + + + + + +#endif // CISTHREAD_H_INCLUDED + + + + -- cgit v1.2.3