diff options
Diffstat (limited to '')
-rw-r--r-- | src/OSSupport/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/OSSupport/CriticalSection.cpp | 52 | ||||
-rw-r--r-- | src/OSSupport/CriticalSection.h | 14 | ||||
-rw-r--r-- | src/OSSupport/IsThread.cpp | 172 | ||||
-rw-r--r-- | src/OSSupport/IsThread.h | 51 | ||||
-rw-r--r-- | src/OSSupport/Sleep.cpp | 19 | ||||
-rw-r--r-- | src/OSSupport/Sleep.h | 7 | ||||
-rw-r--r-- | src/OSSupport/Thread.cpp | 146 | ||||
-rw-r--r-- | src/OSSupport/Thread.h | 26 | ||||
-rw-r--r-- | src/OSSupport/Timer.cpp | 37 | ||||
-rw-r--r-- | src/OSSupport/Timer.h | 32 |
11 files changed, 73 insertions, 489 deletions
diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index 592525941..e943ceb18 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -13,12 +13,9 @@ SET (SRCS IsThread.cpp ListenThread.cpp Semaphore.cpp - Sleep.cpp Socket.cpp SocketThreads.cpp StackTrace.cpp - Thread.cpp - Timer.cpp ) SET (HDRS @@ -31,12 +28,9 @@ SET (HDRS ListenThread.h Queue.h Semaphore.h - Sleep.h Socket.h SocketThreads.h StackTrace.h - Thread.h - Timer.h ) if(NOT MSVC) diff --git a/src/OSSupport/CriticalSection.cpp b/src/OSSupport/CriticalSection.cpp index 5dfc8b5f9..13a3e4d9f 100644 --- a/src/OSSupport/CriticalSection.cpp +++ b/src/OSSupport/CriticalSection.cpp @@ -1,6 +1,5 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules -#include "IsThread.h" @@ -9,41 +8,12 @@ //////////////////////////////////////////////////////////////////////////////// // cCriticalSection: +#ifdef _DEBUG cCriticalSection::cCriticalSection() { - #ifdef _WIN32 - InitializeCriticalSection(&m_CriticalSection); - #else - pthread_mutexattr_init(&m_Attributes); - pthread_mutexattr_settype(&m_Attributes, PTHREAD_MUTEX_RECURSIVE); - - if (pthread_mutex_init(&m_CriticalSection, &m_Attributes) != 0) - { - LOGERROR("Could not initialize Critical Section!"); - } - #endif - - #ifdef _DEBUG - m_IsLocked = 0; - #endif // _DEBUG -} - - - - - -cCriticalSection::~cCriticalSection() -{ - #ifdef _WIN32 - DeleteCriticalSection(&m_CriticalSection); - #else - if (pthread_mutex_destroy(&m_CriticalSection) != 0) - { - LOGWARNING("Could not destroy Critical Section!"); - } - pthread_mutexattr_destroy(&m_Attributes); - #endif + m_IsLocked = 0; } +#endif // _DEBUG @@ -51,15 +21,11 @@ cCriticalSection::~cCriticalSection() void cCriticalSection::Lock() { - #ifdef _WIN32 - EnterCriticalSection(&m_CriticalSection); - #else - pthread_mutex_lock(&m_CriticalSection); - #endif + m_Mutex.lock(); #ifdef _DEBUG m_IsLocked += 1; - m_OwningThreadID = cIsThread::GetCurrentID(); + m_OwningThreadID = std::this_thread::get_id(); #endif // _DEBUG } @@ -74,11 +40,7 @@ void cCriticalSection::Unlock() m_IsLocked -= 1; #endif // _DEBUG - #ifdef _WIN32 - LeaveCriticalSection(&m_CriticalSection); - #else - pthread_mutex_unlock(&m_CriticalSection); - #endif + m_Mutex.unlock(); } @@ -97,7 +59,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..17fcdfc12 100644 --- a/src/OSSupport/CriticalSection.h +++ b/src/OSSupport/CriticalSection.h @@ -1,5 +1,7 @@ #pragma once +#include <mutex> +#include <thread> @@ -8,8 +10,6 @@ class cCriticalSection { public: - cCriticalSection(void); - ~cCriticalSection(); void Lock(void); void Unlock(void); @@ -17,6 +17,7 @@ public: // IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined // The fake versions (in Release) will not effect the program in any way #ifdef _DEBUG + cCriticalSection(void); bool IsLocked(void); bool IsLockedByCurrentThread(void); #else @@ -27,15 +28,10 @@ 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 - CRITICAL_SECTION m_CriticalSection; - #else // _WIN32 - pthread_mutex_t m_CriticalSection; - pthread_mutexattr_t m_Attributes; - #endif // else _WIN32 + std::recursive_mutex m_Mutex; } ALIGN_8; diff --git a/src/OSSupport/IsThread.cpp b/src/OSSupport/IsThread.cpp index 1a436623a..9c62c89bf 100644 --- a/src/OSSupport/IsThread.cpp +++ b/src/OSSupport/IsThread.cpp @@ -5,49 +5,40 @@ // 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 + // 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) + const DWORD MS_VC_EXCEPTION = 0x406D1388; + #pragma pack(push, 8) + struct THREADNAME_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. + }; + #pragma pack(pop) + + /** Sets the name of a thread with the specified ID + (When in MSVC, the debugger provides "thread naming" by catching special exceptions) + */ + static void SetThreadName(std::thread * a_Thread, const char * a_ThreadName) { + THREADNAME_INFO info { 0x1000, a_ThreadName, GetThreadId(a_Thread->native_handle()), 0 }; + __try + { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } } -} #endif // _MSC_VER && _DEBUG @@ -57,13 +48,9 @@ static void SetThreadName(DWORD dwThreadID, const char * threadName) //////////////////////////////////////////////////////////////////////////////// // 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 +70,24 @@ 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) + try + { + m_Thread = std::thread(&cIsThread::Execute, this); + + #if defined (_MSC_VER) && defined(_DEBUG) + if (!m_ThreadName.empty()) { - LOGERROR("ERROR: Could not create thread \"%s\", GLE = %u!", m_ThreadName.c_str(), (unsigned)GetLastError()); - return false; + SetThreadName(&m_Thread, m_ThreadName.c_str()); } - 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 + #endif - return true; + return true; + } + catch (std::system_error & a_Exception) + { + LOGERROR("cIsThread::Wait (std::thread) error %i: could not construct thread %s; %s", a_Exception.code().value(), m_ThreadName.c_str(), a_Exception.what()); + return false; + } } @@ -120,10 +96,6 @@ bool cIsThread::Start(void) void cIsThread::Stop(void) { - if (m_Handle == NULL_HANDLE) - { - return; - } m_ShouldTerminate = true; Wait(); } @@ -134,59 +106,29 @@ 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("cIsThread::Wait (std::thread) error %i: could not join thread %s; %s", a_Exception.code().value(), m_ThreadName.c_str(), 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 5c8d28d2d..131c6950e 100644 --- a/src/OSSupport/IsThread.h +++ b/src/OSSupport/IsThread.h @@ -16,8 +16,7 @@ In the descending class' constructor call the Start() method to start the thread #pragma once -#ifndef CISTHREAD_H_INCLUDED -#define CISTHREAD_H_INCLUDED +#include <thread> @@ -33,7 +32,7 @@ protected: volatile bool m_ShouldTerminate; public: - cIsThread(const AString & iThreadName); + cIsThread(const AString & a_ThreadName); virtual ~cIsThread(); /// Starts the thread; returns without waiting for the actual start @@ -45,56 +44,14 @@ 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) - { - (static_cast<cIsThread *>(a_Param))->Execute(); - return NULL; - } - - #endif // else _WIN32 + std::thread m_Thread; } ; - -#endif // CISTHREAD_H_INCLUDED diff --git a/src/OSSupport/Sleep.cpp b/src/OSSupport/Sleep.cpp deleted file mode 100644 index 297d668d7..000000000 --- a/src/OSSupport/Sleep.cpp +++ /dev/null @@ -1,19 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#ifndef _WIN32 - #include <unistd.h> -#endif - - - - - -void cSleep::MilliSleep( unsigned int a_MilliSeconds) -{ -#ifdef _WIN32 - Sleep(a_MilliSeconds); // Don't tick too much -#else - usleep(a_MilliSeconds*1000); -#endif -} diff --git a/src/OSSupport/Sleep.h b/src/OSSupport/Sleep.h deleted file mode 100644 index 57d29682c..000000000 --- a/src/OSSupport/Sleep.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class cSleep -{ -public: - static void MilliSleep( unsigned int a_MilliSeconds); -}; diff --git a/src/OSSupport/Thread.cpp b/src/OSSupport/Thread.cpp deleted file mode 100644 index 6188d5088..000000000 --- a/src/OSSupport/Thread.cpp +++ /dev/null @@ -1,146 +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 the thread was marked as wait-on-delete, signal the event being waited on: - if (StopEvent != nullptr) - { - 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/OSSupport/Timer.cpp b/src/OSSupport/Timer.cpp deleted file mode 100644 index fd838dd0d..000000000 --- a/src/OSSupport/Timer.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Timer.h" - - - - - - -cTimer::cTimer(void) -{ - #ifdef _WIN32 - QueryPerformanceFrequency(&m_TicksPerSecond); - #endif -} - - - - - -long long cTimer::GetNowTime(void) -{ - #ifdef _WIN32 - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - return ((now.QuadPart * 1000) / m_TicksPerSecond.QuadPart); - #else - struct timeval now; - gettimeofday(&now, NULL); - return (long long)now.tv_sec * 1000 + (long long)now.tv_usec / 1000; - #endif -} - - - - diff --git a/src/OSSupport/Timer.h b/src/OSSupport/Timer.h deleted file mode 100644 index a059daa41..000000000 --- a/src/OSSupport/Timer.h +++ /dev/null @@ -1,32 +0,0 @@ - -// Timer.h - -// Declares the cTimer class representing an OS-independent of retrieving current time with msec accuracy - - - - - -#pragma once - - - - - -class cTimer -{ -public: - cTimer(void); - - // Returns the current time expressed in milliseconds - long long GetNowTime(void); -private: - - #ifdef _WIN32 - LARGE_INTEGER m_TicksPerSecond; - #endif -} ; - - - - |