// // libtgvoip is free and unencumbered public domain software. // For more information, see http://unlicense.org or the UNLICENSE file // you should have received with this source code distribution. // #ifndef __THREADING_H #define __THREADING_H #include #if defined(_POSIX_THREADS) || defined(_POSIX_VERSION) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) #include #include #include #include #ifdef __APPLE__ #include "os/darwin/DarwinSpecific.h" #endif namespace tgvoip{ class Mutex{ public: Mutex(){ pthread_mutex_init(&mtx, NULL); } ~Mutex(){ pthread_mutex_destroy(&mtx); } void Lock(){ pthread_mutex_lock(&mtx); } void Unlock(){ pthread_mutex_unlock(&mtx); } pthread_mutex_t* NativeHandle(){ return &mtx; } private: Mutex(const Mutex& other); pthread_mutex_t mtx; }; class Thread{ public: Thread(std::function entry) : entry(entry){ name=NULL; thread=0; } virtual ~Thread(){ } void Start(){ if(pthread_create(&thread, NULL, Thread::ActualEntryPoint, this)==0){ valid=true; } } void Join(){ if(valid) pthread_join(thread, NULL); } void SetName(const char* name){ this->name=name; } void SetMaxPriority(){ #ifdef __APPLE__ maxPriority=true; #endif } static void Sleep(double seconds){ usleep((useconds_t)(seconds*1000000.0)); } bool IsCurrent(){ return pthread_equal(thread, pthread_self())!=0; } private: static void* ActualEntryPoint(void* arg){ Thread* self=reinterpret_cast(arg); if(self->name){ #if !defined(__APPLE__) && !defined(__gnu_hurd__) pthread_setname_np(self->thread, self->name); #elif !defined(__gnu_hurd__) pthread_setname_np(self->name); if(self->maxPriority){ DarwinSpecific::SetCurrentThreadPriority(DarwinSpecific::THREAD_PRIO_USER_INTERACTIVE); } #endif } self->entry(); return NULL; } std::function entry; pthread_t thread; const char* name; #ifdef __APPLE__ bool maxPriority=false; #endif bool valid=false; }; } #ifdef __APPLE__ #include namespace tgvoip{ class Semaphore{ public: Semaphore(unsigned int maxCount, unsigned int initValue){ sem = dispatch_semaphore_create(initValue); } ~Semaphore(){ #if ! __has_feature(objc_arc) dispatch_release(sem); #endif } void Acquire(){ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); } void Release(){ dispatch_semaphore_signal(sem); } void Acquire(int count){ for(int i=0;i #include namespace tgvoip{ class Mutex{ public: Mutex(){ #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP InitializeCriticalSection(§ion); #else InitializeCriticalSectionEx(§ion, 0, 0); #endif } ~Mutex(){ DeleteCriticalSection(§ion); } void Lock(){ EnterCriticalSection(§ion); } void Unlock(){ LeaveCriticalSection(§ion); } private: Mutex(const Mutex& other); CRITICAL_SECTION section; }; class Thread{ public: Thread(std::function entry) : entry(entry){ name=NULL; thread=NULL; } ~Thread(){ } void Start(){ thread=CreateThread(NULL, 0, Thread::ActualEntryPoint, this, 0, &id); } void Join(){ if(!thread) return; #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP WaitForSingleObject(thread, INFINITE); #else WaitForSingleObjectEx(thread, INFINITE, false); #endif CloseHandle(thread); } void SetName(const char* name){ this->name=name; } void SetMaxPriority(){ SetThreadPriority(thread, THREAD_PRIORITY_HIGHEST); } static void Sleep(double seconds){ ::Sleep((DWORD)(seconds*1000)); } bool IsCurrent(){ return id==GetCurrentThreadId(); } private: static 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 DWORD WINAPI ActualEntryPoint(void* arg){ Thread* self=reinterpret_cast(arg); if(self->name){ THREADNAME_INFO info; info.dwType=0x1000; info.szName=self->name; info.dwThreadID=-1; info.dwFlags=0; __try{ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); }__except(EXCEPTION_EXECUTE_HANDLER){} } self->entry(); return 0; } std::function entry; HANDLE thread; DWORD id; const char* name; }; class Semaphore{ public: Semaphore(unsigned int maxCount, unsigned int initValue){ #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP h=CreateSemaphore(NULL, initValue, maxCount, NULL); #else h=CreateSemaphoreEx(NULL, initValue, maxCount, NULL, 0, SEMAPHORE_ALL_ACCESS); assert(h); #endif } ~Semaphore(){ CloseHandle(h); } void Acquire(){ #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP WaitForSingleObject(h, INFINITE); #else WaitForSingleObjectEx(h, INFINITE, false); #endif } void Release(){ ReleaseSemaphore(h, 1, NULL); } void Acquire(int count){ for(int i=0;i