1 /* 2 * 3 * (C) 2003-2020 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "threadengine.h" 14 #include "anope.h" 15 16 #ifndef _WIN32 17 #include <pthread.h> 18 #endif 19 get_engine_attr()20static inline pthread_attr_t *get_engine_attr() 21 { 22 /* Threadengine attributes used by this thread engine */ 23 static pthread_attr_t attr; 24 static bool inited = false; 25 26 if (inited == false) 27 { 28 if (pthread_attr_init(&attr)) 29 throw CoreException("Error calling pthread_attr_init"); 30 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) 31 throw CoreException("Unable to mark threads as joinable"); 32 inited = true; 33 } 34 35 return &attr; 36 } 37 entry_point(void * parameter)38static void *entry_point(void *parameter) 39 { 40 Thread *thread = static_cast<Thread *>(parameter); 41 thread->Run(); 42 thread->SetExitState(); 43 pthread_exit(0); 44 return NULL; 45 } 46 Thread()47Thread::Thread() : exit(false) 48 { 49 } 50 ~Thread()51Thread::~Thread() 52 { 53 } 54 Join()55void Thread::Join() 56 { 57 this->SetExitState(); 58 pthread_join(handle, NULL); 59 } 60 SetExitState()61void Thread::SetExitState() 62 { 63 this->Notify(); 64 exit = true; 65 } 66 Exit()67void Thread::Exit() 68 { 69 this->SetExitState(); 70 pthread_exit(0); 71 } 72 Start()73void Thread::Start() 74 { 75 if (pthread_create(&this->handle, get_engine_attr(), entry_point, this)) 76 { 77 this->flags[SF_DEAD] = true; 78 throw CoreException("Unable to create thread: " + Anope::LastError()); 79 } 80 } 81 GetExitState() const82bool Thread::GetExitState() const 83 { 84 return exit; 85 } 86 OnNotify()87void Thread::OnNotify() 88 { 89 this->Join(); 90 this->flags[SF_DEAD] = true; 91 } 92 Mutex()93Mutex::Mutex() 94 { 95 pthread_mutex_init(&mutex, NULL); 96 } 97 ~Mutex()98Mutex::~Mutex() 99 { 100 pthread_mutex_destroy(&mutex); 101 } 102 Lock()103void Mutex::Lock() 104 { 105 pthread_mutex_lock(&mutex); 106 } 107 Unlock()108void Mutex::Unlock() 109 { 110 pthread_mutex_unlock(&mutex); 111 } 112 TryLock()113bool Mutex::TryLock() 114 { 115 return pthread_mutex_trylock(&mutex) == 0; 116 } 117 Condition()118Condition::Condition() : Mutex() 119 { 120 pthread_cond_init(&cond, NULL); 121 } 122 ~Condition()123Condition::~Condition() 124 { 125 pthread_cond_destroy(&cond); 126 } 127 Wakeup()128void Condition::Wakeup() 129 { 130 pthread_cond_signal(&cond); 131 } 132 Wait()133void Condition::Wait() 134 { 135 pthread_cond_wait(&cond, &mutex); 136 } 137