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 --- VC2008/MCServer.vcproj | 16 +++-- VC2010/MCServer.vcxproj | 2 + VC2010/MCServer.vcxproj.filters | 2 + makefile | 7 +- source/cIsThread.cpp | 148 ++++++++++++++++++++++++++++++++++++++++ source/cIsThread.h | 77 +++++++++++++++++++++ 6 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 source/cIsThread.cpp create mode 100644 source/cIsThread.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index ef5f1d3c1..1698616c4 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -435,10 +435,6 @@ RelativePath="..\source\cServer.h" > - - @@ -1290,6 +1286,10 @@ RelativePath="..\source\cPlayer.h" > + + @@ -1434,6 +1434,14 @@ RelativePath="..\source\cFile.h" > + + + + diff --git a/VC2010/MCServer.vcxproj b/VC2010/MCServer.vcxproj index 3698a757d..4cdd9d15c 100644 --- a/VC2010/MCServer.vcxproj +++ b/VC2010/MCServer.vcxproj @@ -330,6 +330,7 @@ + @@ -496,6 +497,7 @@ + diff --git a/VC2010/MCServer.vcxproj.filters b/VC2010/MCServer.vcxproj.filters index d605360b0..031f6588a 100644 --- a/VC2010/MCServer.vcxproj.filters +++ b/VC2010/MCServer.vcxproj.filters @@ -910,6 +910,7 @@ + @@ -1401,6 +1402,7 @@ + diff --git a/makefile b/makefile index 0f92fe58a..bf183922f 100644 --- a/makefile +++ b/makefile @@ -248,7 +248,8 @@ MCServer : \ build/cItem.o\ build/cPlugin_NewLua.o\ build/cWebPlugin_Lua.o\ - build/StringUtils.o + build/StringUtils.o\ + build/cIsThread.o $(CC) $(LNK_OPTIONS) \ build/json_reader.o\ build/json_value.o\ @@ -460,6 +461,7 @@ MCServer : \ build/cPlugin_NewLua.o\ build/cWebPlugin_Lua.o\ build/StringUtils.o\ + build/cIsThread.o\ -o MCServer clean : @@ -1534,4 +1536,7 @@ build/cWebPlugin_Lua.o : source/cWebPlugin_Lua.cpp build/StringUtils.o : source/StringUtils.cpp $(CC) $(CC_OPTIONS) source/StringUtils.cpp -c $(INCLUDE) -o build/StringUtils.o +build/cIsThread.o : source/cIsThread.cpp + $(CC) $(CC_OPTIONS) source/cIsThread.cpp -c $(INCLUDE) -o build/cIsThread.o + ##### END RUN #### 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