1
0

new cIsThread object for thread encapsulation

git-svn-id: http://mc-server.googlecode.com/svn/trunk@214 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-02-01 12:25:26 +00:00
parent 8f5e834f41
commit 83fc392198
6 changed files with 247 additions and 5 deletions

View File

@ -435,10 +435,6 @@
RelativePath="..\source\cServer.h"
>
</File>
<File
RelativePath="..\source\cSign.h"
>
</File>
<File
RelativePath="..\source\cSimulator.cpp"
>
@ -1290,6 +1286,10 @@
RelativePath="..\source\cPlayer.h"
>
</File>
<File
RelativePath="..\source\cSign.h"
>
</File>
<File
RelativePath="..\source\cSignEntity.cpp"
>
@ -1434,6 +1434,14 @@
RelativePath="..\source\cFile.h"
>
</File>
<File
RelativePath="..\source\cIsThread.cpp"
>
</File>
<File
RelativePath="..\source\cIsThread.h"
>
</File>
<File
RelativePath="..\source\cMakeDir.cpp"
>

View File

@ -330,6 +330,7 @@
<ClCompile Include="..\Source\cGroup.cpp" />
<ClCompile Include="..\Source\cGroupManager.cpp" />
<ClCompile Include="..\Source\cHeartBeat.cpp" />
<ClCompile Include="..\source\cIsThread.cpp" />
<ClCompile Include="..\source\cItem.cpp" />
<ClCompile Include="..\source\cLavaSimulator.cpp" />
<ClCompile Include="..\Source\cLuaCommandBinder.cpp" />
@ -496,6 +497,7 @@
<ClInclude Include="..\Source\cGroup.h" />
<ClInclude Include="..\Source\cGroupManager.h" />
<ClInclude Include="..\Source\cHeartBeat.h" />
<ClInclude Include="..\source\cIsThread.h" />
<ClInclude Include="..\Source\cLadder.h" />
<ClInclude Include="..\source\cLavaSimulator.h" />
<ClInclude Include="..\Source\cLuaCommandBinder.h" />

View File

@ -910,6 +910,7 @@
<ClCompile Include="..\source\Globals.cpp" />
<ClCompile Include="..\source\cFile.cpp" />
<ClCompile Include="..\source\StringUtils.cpp" />
<ClCompile Include="..\source\cIsThread.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\source\cServer.h">
@ -1401,6 +1402,7 @@
<ClInclude Include="..\source\Globals.h" />
<ClInclude Include="..\source\cFile.h" />
<ClInclude Include="..\source\StringUtils.h" />
<ClInclude Include="..\source\cIsThread.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\source\AllToLua.pkg">

View File

@ -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 ####

148
source/cIsThread.cpp Normal file
View File

@ -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
}

77
source/cIsThread.h Normal file
View File

@ -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