| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- //
- // 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 <functional>
- #if defined(_POSIX_THREADS) || defined(_POSIX_VERSION) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
- #include <pthread.h>
- #include <semaphore.h>
- #include <sched.h>
- #include <unistd.h>
- #if defined(__APPLE__)
- #include "os/darwin/DarwinSpecific.h"
- #elif defined(__FreeBSD__) || defined(__OpenBSD__)
- #include <pthread_np.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<void()> 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<Thread*>(arg);
- if(self->name){
- #if defined(__linux__) || defined(__FreeBSD__)
- pthread_setname_np(self->thread, self->name);
- #elif defined(__OpenBSD__)
- pthread_set_name_np(self->thread, self->name);
- #elif defined(__APPLE__)
- pthread_setname_np(self->name);
- if(self->maxPriority){
- DarwinSpecific::SetCurrentThreadPriority(DarwinSpecific::THREAD_PRIO_USER_INTERACTIVE);
- }
- #endif
- }
- self->entry();
- return NULL;
- }
- std::function<void()> entry;
- pthread_t thread;
- const char* name;
- #ifdef __APPLE__
- bool maxPriority=false;
- #endif
- bool valid=false;
- };
- }
- #ifdef __APPLE__
- #include <dispatch/dispatch.h>
- 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<count;i++)
- Acquire();
- }
- void Release(int count){
- for(int i=0;i<count;i++)
- Release();
- }
- private:
- dispatch_semaphore_t sem;
- };
- }
- #else
- namespace tgvoip{
- class Semaphore{
- public:
- Semaphore(unsigned int maxCount, unsigned int initValue){
- sem_init(&sem, 0, initValue);
- }
- ~Semaphore(){
- sem_destroy(&sem);
- }
- void Acquire(){
- sem_wait(&sem);
- }
- void Release(){
- sem_post(&sem);
- }
- void Acquire(int count){
- for(int i=0;i<count;i++)
- Acquire();
- }
- void Release(int count){
- for(int i=0;i<count;i++)
- Release();
- }
- private:
- sem_t sem;
- };
- }
- #endif
- #elif defined(_WIN32)
- #define TGVOIP_WIN32_THREADING
- #include <Windows.h>
- #include <assert.h>
- 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<void()> 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<Thread*>(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<void()> 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<count;i++)
- Acquire();
- }
- void Release(int count){
- ReleaseSemaphore(h, count, NULL);
- }
- private:
- HANDLE h;
- };
- }
- #else
- #error "No threading implementation for your operating system"
- #endif
- namespace tgvoip{
- class MutexGuard{
- public:
- MutexGuard(Mutex &mutex) : mutex(mutex) {
- mutex.Lock();
- }
- ~MutexGuard(){
- mutex.Unlock();
- }
- private:
- Mutex &mutex;
- };
- }
- #endif //__THREADING_H
|