From 6d5a8892f34f4034b38da467268de9d489e1024e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Oct 2014 00:29:34 +0100 Subject: Use std::thread --- src/ByteBuffer.cpp | 74 ------------------ src/ByteBuffer.h | 4 - src/Globals.h | 2 +- src/Logger.cpp | 2 +- src/OSSupport/CMakeLists.txt | 2 - src/OSSupport/CriticalSection.cpp | 4 +- src/OSSupport/CriticalSection.h | 2 +- src/OSSupport/IsThread.cpp | 158 +++++++------------------------------- src/OSSupport/IsThread.h | 44 +---------- src/OSSupport/Thread.cpp | 137 --------------------------------- src/OSSupport/Thread.h | 26 ------- src/Root.cpp | 30 +++++--- src/Root.h | 6 +- 13 files changed, 59 insertions(+), 432 deletions(-) delete mode 100644 src/OSSupport/Thread.cpp delete mode 100644 src/OSSupport/Thread.h diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index dc6b32a44..d03b6bbe4 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -109,46 +109,12 @@ public: -#ifdef _DEBUG - -/// Simple RAII class that uses one internal unsigned long for checking if two threads are using an object simultanously -class cSingleThreadAccessChecker -{ -public: - cSingleThreadAccessChecker(unsigned long * a_ThreadID) : - m_ThreadID(a_ThreadID) - { - ASSERT((*a_ThreadID == 0) || (*a_ThreadID == cIsThread::GetCurrentID())); - } - - ~cSingleThreadAccessChecker() - { - *m_ThreadID = 0; - } - -protected: - unsigned long * m_ThreadID; -} ; - -#define CHECK_THREAD cSingleThreadAccessChecker Checker(const_cast(&m_ThreadID)) - -#else - #define CHECK_THREAD -#endif - - - - - //////////////////////////////////////////////////////////////////////////////// // cByteBuffer: cByteBuffer::cByteBuffer(size_t a_BufferSize) : m_Buffer(new char[a_BufferSize + 1]), m_BufferSize(a_BufferSize + 1), - #ifdef _DEBUG - m_ThreadID(0), - #endif // _DEBUG m_DataStart(0), m_WritePos(0), m_ReadPos(0) @@ -174,7 +140,6 @@ cByteBuffer::~cByteBuffer() bool cByteBuffer::Write(const void * a_Bytes, size_t a_Count) { - CHECK_THREAD; CheckValid(); // Store the current free space for a check after writing: @@ -221,7 +186,6 @@ bool cByteBuffer::Write(const void * a_Bytes, size_t a_Count) size_t cByteBuffer::GetFreeSpace(void) const { - CHECK_THREAD; CheckValid(); if (m_WritePos >= m_DataStart) { @@ -243,7 +207,6 @@ size_t cByteBuffer::GetFreeSpace(void) const /// Returns the number of bytes that are currently in the ringbuffer. Note GetReadableBytes() size_t cByteBuffer::GetUsedSpace(void) const { - CHECK_THREAD; CheckValid(); ASSERT(m_BufferSize >= GetFreeSpace()); ASSERT((m_BufferSize - GetFreeSpace()) >= 1); @@ -257,7 +220,6 @@ size_t cByteBuffer::GetUsedSpace(void) const /// Returns the number of bytes that are currently available for reading (may be less than UsedSpace due to some data having been read already) size_t cByteBuffer::GetReadableSpace(void) const { - CHECK_THREAD; CheckValid(); if (m_ReadPos > m_WritePos) { @@ -276,7 +238,6 @@ size_t cByteBuffer::GetReadableSpace(void) const bool cByteBuffer::CanReadBytes(size_t a_Count) const { - CHECK_THREAD; CheckValid(); return (a_Count <= GetReadableSpace()); } @@ -287,7 +248,6 @@ bool cByteBuffer::CanReadBytes(size_t a_Count) const bool cByteBuffer::CanWriteBytes(size_t a_Count) const { - CHECK_THREAD; CheckValid(); return (a_Count <= GetFreeSpace()); } @@ -298,7 +258,6 @@ bool cByteBuffer::CanWriteBytes(size_t a_Count) const bool cByteBuffer::ReadChar(char & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(1); ReadBuf(&a_Value, 1); @@ -311,7 +270,6 @@ bool cByteBuffer::ReadChar(char & a_Value) bool cByteBuffer::ReadByte(unsigned char & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(1); ReadBuf(&a_Value, 1); @@ -324,7 +282,6 @@ bool cByteBuffer::ReadByte(unsigned char & a_Value) bool cByteBuffer::ReadBEShort(short & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(2); ReadBuf(&a_Value, 2); @@ -338,7 +295,6 @@ bool cByteBuffer::ReadBEShort(short & a_Value) bool cByteBuffer::ReadBEInt(int & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(4); ReadBuf(&a_Value, 4); @@ -352,7 +308,6 @@ bool cByteBuffer::ReadBEInt(int & a_Value) bool cByteBuffer::ReadBEInt64(Int64 & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(8); ReadBuf(&a_Value, 8); @@ -366,7 +321,6 @@ bool cByteBuffer::ReadBEInt64(Int64 & a_Value) bool cByteBuffer::ReadBEFloat(float & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(4); ReadBuf(&a_Value, 4); @@ -380,7 +334,6 @@ bool cByteBuffer::ReadBEFloat(float & a_Value) bool cByteBuffer::ReadBEDouble(double & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(8); ReadBuf(&a_Value, 8); @@ -394,7 +347,6 @@ bool cByteBuffer::ReadBEDouble(double & a_Value) bool cByteBuffer::ReadBool(bool & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(1); char Value = 0; @@ -409,7 +361,6 @@ bool cByteBuffer::ReadBool(bool & a_Value) bool cByteBuffer::ReadBEUTF16String16(AString & a_Value) { - CHECK_THREAD; CheckValid(); short Length; if (!ReadBEShort(Length)) @@ -430,7 +381,6 @@ bool cByteBuffer::ReadBEUTF16String16(AString & a_Value) bool cByteBuffer::ReadVarInt(UInt32 & a_Value) { - CHECK_THREAD; CheckValid(); UInt32 Value = 0; int Shift = 0; @@ -452,7 +402,6 @@ bool cByteBuffer::ReadVarInt(UInt32 & a_Value) bool cByteBuffer::ReadVarUTF8String(AString & a_Value) { - CHECK_THREAD; CheckValid(); UInt32 Size = 0; if (!ReadVarInt(Size)) @@ -472,7 +421,6 @@ bool cByteBuffer::ReadVarUTF8String(AString & a_Value) bool cByteBuffer::ReadLEInt(int & a_Value) { - CHECK_THREAD; CheckValid(); NEEDBYTES(4); ReadBuf(&a_Value, 4); @@ -515,7 +463,6 @@ bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ) bool cByteBuffer::WriteChar(char a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(1); return WriteBuf(&a_Value, 1); @@ -527,7 +474,6 @@ bool cByteBuffer::WriteChar(char a_Value) bool cByteBuffer::WriteByte(unsigned char a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(1); return WriteBuf(&a_Value, 1); @@ -539,7 +485,6 @@ bool cByteBuffer::WriteByte(unsigned char a_Value) bool cByteBuffer::WriteBEShort(short a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(2); u_short Converted = htons((u_short)a_Value); @@ -552,7 +497,6 @@ bool cByteBuffer::WriteBEShort(short a_Value) bool cByteBuffer::WriteBEUShort(unsigned short a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(2); u_short Converted = htons((u_short)a_Value); @@ -565,7 +509,6 @@ bool cByteBuffer::WriteBEUShort(unsigned short a_Value) bool cByteBuffer::WriteBEInt(int a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(4); UInt32 Converted = HostToNetwork4(&a_Value); @@ -578,7 +521,6 @@ bool cByteBuffer::WriteBEInt(int a_Value) bool cByteBuffer::WriteBEInt64(Int64 a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(8); UInt64 Converted = HostToNetwork8(&a_Value); @@ -591,7 +533,6 @@ bool cByteBuffer::WriteBEInt64(Int64 a_Value) bool cByteBuffer::WriteBEFloat(float a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(4); UInt32 Converted = HostToNetwork4(&a_Value); @@ -604,7 +545,6 @@ bool cByteBuffer::WriteBEFloat(float a_Value) bool cByteBuffer::WriteBEDouble(double a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(8); UInt64 Converted = HostToNetwork8(&a_Value); @@ -618,7 +558,6 @@ bool cByteBuffer::WriteBEDouble(double a_Value) bool cByteBuffer::WriteBool(bool a_Value) { - CHECK_THREAD; CheckValid(); return WriteChar(a_Value ? 1 : 0); } @@ -629,7 +568,6 @@ bool cByteBuffer::WriteBool(bool a_Value) bool cByteBuffer::WriteVarInt(UInt32 a_Value) { - CHECK_THREAD; CheckValid(); // A 32-bit integer can be encoded by at most 5 bytes: @@ -650,7 +588,6 @@ bool cByteBuffer::WriteVarInt(UInt32 a_Value) bool cByteBuffer::WriteVarUTF8String(const AString & a_Value) { - CHECK_THREAD; CheckValid(); PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early. bool res = WriteVarInt((UInt32)(a_Value.size())); @@ -667,7 +604,6 @@ bool cByteBuffer::WriteVarUTF8String(const AString & a_Value) bool cByteBuffer::WriteLEInt(int a_Value) { - CHECK_THREAD; CheckValid(); #ifdef IS_LITTLE_ENDIAN return WriteBuf((const char *)&a_Value, 4); @@ -692,7 +628,6 @@ bool cByteBuffer::WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ) bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count) { - CHECK_THREAD; CheckValid(); NEEDBYTES(a_Count); char * Dst = (char *)a_Buffer; // So that we can do byte math @@ -725,7 +660,6 @@ bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count) bool cByteBuffer::WriteBuf(const void * a_Buffer, size_t a_Count) { - CHECK_THREAD; CheckValid(); PUTBYTES(a_Count); char * Src = (char *)a_Buffer; // So that we can do byte math @@ -755,7 +689,6 @@ bool cByteBuffer::WriteBuf(const void * a_Buffer, size_t a_Count) bool cByteBuffer::ReadString(AString & a_String, size_t a_Count) { - CHECK_THREAD; CheckValid(); NEEDBYTES(a_Count); a_String.clear(); @@ -790,7 +723,6 @@ bool cByteBuffer::ReadString(AString & a_String, size_t a_Count) bool cByteBuffer::ReadUTF16String(AString & a_String, size_t a_NumChars) { // Reads 2 * a_NumChars bytes and interprets it as a UTF16 string, converting it into UTF8 string a_String - CHECK_THREAD; CheckValid(); AString RawData; if (!ReadString(RawData, a_NumChars * 2)) @@ -807,7 +739,6 @@ bool cByteBuffer::ReadUTF16String(AString & a_String, size_t a_NumChars) bool cByteBuffer::SkipRead(size_t a_Count) { - CHECK_THREAD; CheckValid(); if (!CanReadBytes(a_Count)) { @@ -823,7 +754,6 @@ bool cByteBuffer::SkipRead(size_t a_Count) void cByteBuffer::ReadAll(AString & a_Data) { - CHECK_THREAD; CheckValid(); ReadString(a_Data, GetReadableSpace()); } @@ -858,7 +788,6 @@ bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes) void cByteBuffer::CommitRead(void) { - CHECK_THREAD; CheckValid(); m_DataStart = m_ReadPos; } @@ -869,7 +798,6 @@ void cByteBuffer::CommitRead(void) void cByteBuffer::ResetRead(void) { - CHECK_THREAD; CheckValid(); m_ReadPos = m_DataStart; } @@ -882,7 +810,6 @@ void cByteBuffer::ReadAgain(AString & a_Out) { // Return the data between m_DataStart and m_ReadPos (the data that has been read but not committed) // Used by ProtoProxy to repeat communication twice, once for parsing and the other time for the remote party - CHECK_THREAD; CheckValid(); size_t DataStart = m_DataStart; if (m_ReadPos < m_DataStart) @@ -902,7 +829,6 @@ void cByteBuffer::ReadAgain(AString & a_Out) void cByteBuffer::AdvanceReadPos(size_t a_Count) { - CHECK_THREAD; CheckValid(); m_ReadPos += a_Count; if (m_ReadPos >= m_BufferSize) diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h index 70de419f0..e80763772 100644 --- a/src/ByteBuffer.h +++ b/src/ByteBuffer.h @@ -130,10 +130,6 @@ protected: char * m_Buffer; size_t m_BufferSize; // Total size of the ringbuffer - #ifdef _DEBUG - volatile unsigned long m_ThreadID; // Thread that is currently accessing the object, checked via cSingleThreadAccessChecker - #endif // _DEBUG - size_t m_DataStart; // Where the data starts in the ringbuffer size_t m_WritePos; // Where the data ends in the ringbuffer size_t m_ReadPos; // Where the next read will start in the ringbuffer diff --git a/src/Globals.h b/src/Globals.h index b84607355..f6c722594 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -239,6 +239,7 @@ template class SizeChecker; // STL stuff: +#include #include #include #include @@ -259,7 +260,6 @@ template class SizeChecker; #include "OSSupport/CriticalSection.h" #include "OSSupport/Semaphore.h" #include "OSSupport/Event.h" - #include "OSSupport/Thread.h" #include "OSSupport/File.h" #include "Logger.h" #else diff --git a/src/Logger.cpp b/src/Logger.cpp index cb528e8ab..fad4a5e75 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -45,7 +45,7 @@ void cLogger::LogSimple(AString a_Message, eLogLevel a_LogLevel) AString Line; #ifdef _DEBUG - Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str()); + Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", std::this_thread::get_id().hash(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str()); #else Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str()); #endif diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index 429949c59..1c8da5ddd 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -16,7 +16,6 @@ SET (SRCS Sleep.cpp Socket.cpp SocketThreads.cpp - Thread.cpp Timer.cpp) SET (HDRS @@ -32,7 +31,6 @@ SET (HDRS Sleep.h Socket.h SocketThreads.h - Thread.h Timer.h) if(NOT MSVC) diff --git a/src/OSSupport/CriticalSection.cpp b/src/OSSupport/CriticalSection.cpp index 5dfc8b5f9..3e8e7498d 100644 --- a/src/OSSupport/CriticalSection.cpp +++ b/src/OSSupport/CriticalSection.cpp @@ -59,7 +59,7 @@ void cCriticalSection::Lock() #ifdef _DEBUG m_IsLocked += 1; - m_OwningThreadID = cIsThread::GetCurrentID(); + m_OwningThreadID = std::this_thread::get_id(); #endif // _DEBUG } @@ -97,7 +97,7 @@ bool cCriticalSection::IsLocked(void) bool cCriticalSection::IsLockedByCurrentThread(void) { - return ((m_IsLocked > 0) && (m_OwningThreadID == cIsThread::GetCurrentID())); + return ((m_IsLocked > 0) && (m_OwningThreadID == std::this_thread::get_id())); } #endif // _DEBUG diff --git a/src/OSSupport/CriticalSection.h b/src/OSSupport/CriticalSection.h index c3c6e57f0..7822a5471 100644 --- a/src/OSSupport/CriticalSection.h +++ b/src/OSSupport/CriticalSection.h @@ -27,7 +27,7 @@ public: private: #ifdef _DEBUG int m_IsLocked; // Number of times this CS is locked - unsigned long m_OwningThreadID; + std::thread::id m_OwningThreadID; #endif // _DEBUG #ifdef _WIN32 diff --git a/src/OSSupport/IsThread.cpp b/src/OSSupport/IsThread.cpp index 1a436623a..4864ef28b 100644 --- a/src/OSSupport/IsThread.cpp +++ b/src/OSSupport/IsThread.cpp @@ -5,65 +5,18 @@ // This class will eventually suupersede the old cThread class #include "Globals.h" - #include "IsThread.h" -// When in MSVC, the debugger provides "thread naming" by catching special exceptions. Interface here: -#if defined(_MSC_VER) && defined(_DEBUG) -// -// Usage: SetThreadName (-1, "MainThread"); -// - -// Code adapted from MSDN: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - -const DWORD MS_VC_EXCEPTION = 0x406D1388; - -#pragma pack(push, 8) -typedef struct tagTHREADNAME_INFO -{ - 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. -} THREADNAME_INFO; -#pragma pack(pop) - -static void SetThreadName(DWORD dwThreadID, const char * threadName) -{ - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try - { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } -} -#endif // _MSC_VER && _DEBUG - - - - - //////////////////////////////////////////////////////////////////////////////// // cIsThread: -cIsThread::cIsThread(const AString & iThreadName) : +cIsThread::cIsThread(const AString & a_ThreadName) : m_ShouldTerminate(false), - m_ThreadName(iThreadName), - #ifdef _WIN32 - m_ThreadID(0), - #endif - m_Handle(NULL_HANDLE) + m_ThreadName(a_ThreadName) { } @@ -83,35 +36,16 @@ cIsThread::~cIsThread() bool cIsThread::Start(void) { - ASSERT(m_Handle == NULL_HANDLE); // Has already started one thread? - #ifdef _WIN32 - // Create the thread suspended, so that the mHandle variable is valid in the thread procedure - m_ThreadID = 0; - m_Handle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &m_ThreadID); - if (m_Handle == NULL) - { - LOGERROR("ERROR: Could not create thread \"%s\", GLE = %u!", m_ThreadName.c_str(), (unsigned)GetLastError()); - return false; - } - ResumeThread(m_Handle); - - #if defined(_DEBUG) && defined(_MSC_VER) - // Thread naming is available only in MSVC - if (!m_ThreadName.empty()) - { - SetThreadName(m_ThreadID, m_ThreadName.c_str()); - } - #endif // _DEBUG and _MSC_VER - - #else // _WIN32 - if (pthread_create(&m_Handle, NULL, thrExecute, this)) - { - LOGERROR("ERROR: Could not create thread \"%s\", !", m_ThreadName.c_str()); - return false; - } - #endif // else _WIN32 - - return true; + try + { + m_Thread = std::thread(&cIsThread::Execute, this); + return true; + } + catch (std::system_error & a_Exception) + { + LOGERROR("ERROR: Could not create thread \"%s\", error = %s!", m_ThreadName.c_str(), a_Exception.code(), a_Exception.what()); + return false; + } } @@ -120,10 +54,6 @@ bool cIsThread::Start(void) void cIsThread::Stop(void) { - if (m_Handle == NULL_HANDLE) - { - return; - } m_ShouldTerminate = true; Wait(); } @@ -133,60 +63,30 @@ void cIsThread::Stop(void) bool cIsThread::Wait(void) -{ - if (m_Handle == NULL_HANDLE) - { - return true; - } - +{ #ifdef LOGD // ProtoProxy doesn't have LOGD LOGD("Waiting for thread %s to finish", m_ThreadName.c_str()); #endif // LOGD - - #ifdef _WIN32 - int res = WaitForSingleObject(m_Handle, INFINITE); - m_Handle = NULL; - - #ifdef LOGD // ProtoProxy doesn't have LOGD - LOGD("Thread %s finished", m_ThreadName.c_str()); - #endif // LOGD - - return (res == WAIT_OBJECT_0); - #else // _WIN32 - int res = pthread_join(m_Handle, NULL); - m_Handle = NULL_HANDLE; - - #ifdef LOGD // ProtoProxy doesn't have LOGD - LOGD("Thread %s finished", m_ThreadName.c_str()); - #endif // LOGD - - return (res == 0); - #endif // else _WIN32 -} - - - + if (m_Thread.joinable()) + { + try + { + m_Thread.join(); + return true; + } + catch (std::system_error & a_Exception) + { + LOGERROR("ERROR: Could wait for thread \"%s\" to finish, error = %s!", m_ThreadName.c_str(), a_Exception.code(), a_Exception.what()); + return false; + } + } -unsigned long cIsThread::GetCurrentID(void) -{ - #ifdef _WIN32 - return (unsigned long) GetCurrentThreadId(); - #else - return (unsigned long) pthread_self(); + #ifdef LOGD // ProtoProxy doesn't have LOGD + LOGD("Thread %s finished", m_ThreadName.c_str()); #endif -} - - - -bool cIsThread::IsCurrentThread(void) const -{ - #ifdef _WIN32 - return (GetCurrentThreadId() == m_ThreadID); - #else - return (m_Handle == pthread_self()); - #endif + return true; } diff --git a/src/OSSupport/IsThread.h b/src/OSSupport/IsThread.h index 5de5f31c4..8dfad84cb 100644 --- a/src/OSSupport/IsThread.h +++ b/src/OSSupport/IsThread.h @@ -44,53 +44,13 @@ public: /// Waits for the thread to finish. Doesn't signalize the ShouldTerminate flag bool Wait(void); - - /// Returns the OS-dependent thread ID for the caller's thread - static unsigned long GetCurrentID(void); /** Returns true if the thread calling this function is the thread contained within this object. */ - bool IsCurrentThread(void) const; + bool IsCurrentThread(void) const { return std::this_thread::get_id() == m_Thread.get_id(); } protected: AString m_ThreadName; - - // Value used for "no handle": - #ifdef _WIN32 - #define NULL_HANDLE NULL - #else - #define NULL_HANDLE 0 - #endif - - #ifdef _WIN32 - - DWORD m_ThreadID; - HANDLE m_Handle; - - static DWORD __stdcall thrExecute(LPVOID a_Param) - { - // Create a window so that the thread can be identified by 3rd party tools: - HWND IdentificationWnd = CreateWindowA("STATIC", ((cIsThread *)a_Param)->m_ThreadName.c_str(), 0, 0, 0, 0, WS_OVERLAPPED, NULL, NULL, NULL, NULL); - - // Run the thread: - ((cIsThread *)a_Param)->Execute(); - - // Destroy the identification window: - DestroyWindow(IdentificationWnd); - - return 0; - } - - #else // _WIN32 - - pthread_t m_Handle; - - static void * thrExecute(void * a_Param) - { - ((cIsThread *)a_Param)->Execute(); - return NULL; - } - - #endif // else _WIN32 + std::thread m_Thread; } ; diff --git a/src/OSSupport/Thread.cpp b/src/OSSupport/Thread.cpp deleted file mode 100644 index faaccce96..000000000 --- a/src/OSSupport/Thread.cpp +++ /dev/null @@ -1,137 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - - - - - -// When in MSVC, the debugger provides "thread naming" by catching special exceptions. Interface here: -#ifdef _MSC_VER -// -// Usage: SetThreadName (-1, "MainThread"); -// - -// Code adapted from MSDN: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - -const DWORD MS_VC_EXCEPTION = 0x406D1388; - -#pragma pack(push, 8) -typedef struct tagTHREADNAME_INFO -{ - 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. -} THREADNAME_INFO; -#pragma pack(pop) - -static void SetThreadName(DWORD dwThreadID, const char * threadName) -{ - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try - { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } -} -#endif // _MSC_VER - - - - - -cThread::cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName /* = 0 */) - : m_ThreadFunction( a_ThreadFunction) - , m_Param( a_Param) - , m_Event( new cEvent()) - , m_StopEvent( 0) -{ - if (a_ThreadName) - { - m_ThreadName.assign(a_ThreadName); - } -} - - - - - -cThread::~cThread() -{ - delete m_Event; - m_Event = NULL; - - if (m_StopEvent) - { - m_StopEvent->Wait(); - delete m_StopEvent; - m_StopEvent = NULL; - } -} - - - - - -void cThread::Start( bool a_bWaitOnDelete /* = true */) -{ - if (a_bWaitOnDelete) - m_StopEvent = new cEvent(); - -#ifndef _WIN32 - pthread_t SndThread; - if (pthread_create( &SndThread, NULL, MyThread, this)) - LOGERROR("ERROR: Could not create thread!"); -#else - DWORD ThreadID = 0; - HANDLE hThread = CreateThread(NULL // security - , 0 // stack size - , (LPTHREAD_START_ROUTINE) MyThread // function name - , this // parameters - , 0 // flags - , &ThreadID); // thread id - CloseHandle( hThread); - - #ifdef _MSC_VER - if (!m_ThreadName.empty()) - { - SetThreadName(ThreadID, m_ThreadName.c_str()); - } - #endif // _MSC_VER -#endif - - // Wait until thread has actually been created - m_Event->Wait(); -} - - - - - -#ifdef _WIN32 -unsigned long cThread::MyThread(void* a_Param) -#else -void *cThread::MyThread( void *a_Param) -#endif -{ - cThread* self = (cThread*)a_Param; - cEvent* StopEvent = self->m_StopEvent; - - ThreadFunc* ThreadFunction = self->m_ThreadFunction; - void* ThreadParam = self->m_Param; - - // Set event to let other thread know this thread has been created and it's safe to delete the cThread object - self->m_Event->Set(); - - ThreadFunction( ThreadParam); - - if (StopEvent) StopEvent->Set(); - return 0; -} diff --git a/src/OSSupport/Thread.h b/src/OSSupport/Thread.h deleted file mode 100644 index 7ee352c82..000000000 --- a/src/OSSupport/Thread.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -class cThread -{ -public: - typedef void (ThreadFunc)(void*); - cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName = 0); - ~cThread(); - - void Start( bool a_bWaitOnDelete = true); - void WaitForThread(); -private: - ThreadFunc* m_ThreadFunction; - -#ifdef _WIN32 - static unsigned long MyThread(void* a_Param); -#else - static void *MyThread( void *lpParam); -#endif - - void* m_Param; - cEvent* m_Event; - cEvent* m_StopEvent; - - AString m_ThreadName; -}; diff --git a/src/Root.cpp b/src/Root.cpp index 2d08c2c70..2cfbf0817 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -43,7 +43,6 @@ cRoot* cRoot::s_Root = NULL; cRoot::cRoot(void) : m_pDefaultWorld(NULL), - m_InputThread(NULL), m_Server(NULL), m_MonsterConfig(NULL), m_CraftingRecipes(NULL), @@ -69,26 +68,24 @@ cRoot::~cRoot() -void cRoot::InputThread(void * a_Params) +void cRoot::InputThread(cRoot * a_Params) { - cRoot & self = *(cRoot*)a_Params; - cLogCommandOutputCallback Output; - while (!self.m_bStop && !self.m_bRestart && !m_TerminateEventRaised && std::cin.good()) + while (!a_Params->m_bStop && !a_Params->m_bRestart && !m_TerminateEventRaised && std::cin.good()) { AString Command; std::getline(std::cin, Command); if (!Command.empty()) { - self.ExecuteConsoleCommand(TrimString(Command), Output); + a_Params->ExecuteConsoleCommand(TrimString(Command), Output); } } if (m_TerminateEventRaised || !std::cin.good()) { // We have come here because the std::cin has received an EOF / a terminate signal has been sent, and the server is still running; stop the server: - self.m_bStop = true; + a_Params->m_bStop = true; } } @@ -191,8 +188,14 @@ void cRoot::Start(void) #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); - m_InputThread = new cThread( InputThread, this, "cRoot::InputThread"); - m_InputThread->Start( false); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread + try + { + m_InputThread = std::thread(InputThread, this); + } + catch (std::system_error & a_Exception) + { + LOGERROR("ERROR: Could not create input thread, error = %s!", a_Exception.code(), a_Exception.what()); + } #endif long long finishmseconds = Time.GetNowTime(); @@ -214,7 +217,14 @@ void cRoot::Start(void) } #if !defined(ANDROID_NDK) - delete m_InputThread; m_InputThread = NULL; + try + { + m_InputThread.join(); + } + catch (std::system_error & a_Exception) + { + LOGERROR("ERROR: Could not wait for input thread to finish, error = %s!", a_Exception.code(), a_Exception.what()); + } #endif // Stop the server: diff --git a/src/Root.h b/src/Root.h index 84c6a98ec..7c7798315 100644 --- a/src/Root.h +++ b/src/Root.h @@ -174,7 +174,7 @@ private: cCriticalSection m_CSPendingCommands; cCommandQueue m_PendingCommands; - cThread * m_InputThread; + std::thread m_InputThread; cServer * m_Server; cMonsterConfig * m_MonsterConfig; @@ -207,10 +207,10 @@ private: /// Does the actual work of executing a command void DoExecuteConsoleCommand(const AString & a_Cmd); - - static void InputThread(void* a_Params); static cRoot* s_Root; + + static void InputThread(cRoot * a_Params); }; // tolua_export -- cgit v1.2.3