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()20 static 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)38 static 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()47 Thread::Thread() : exit(false)
48 {
49 }
50 
~Thread()51 Thread::~Thread()
52 {
53 }
54 
Join()55 void Thread::Join()
56 {
57 	this->SetExitState();
58 	pthread_join(handle, NULL);
59 }
60 
SetExitState()61 void Thread::SetExitState()
62 {
63 	this->Notify();
64 	exit = true;
65 }
66 
Exit()67 void Thread::Exit()
68 {
69 	this->SetExitState();
70 	pthread_exit(0);
71 }
72 
Start()73 void 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() const82 bool Thread::GetExitState() const
83 {
84 	return exit;
85 }
86 
OnNotify()87 void Thread::OnNotify()
88 {
89 	this->Join();
90 	this->flags[SF_DEAD] = true;
91 }
92 
Mutex()93 Mutex::Mutex()
94 {
95 	pthread_mutex_init(&mutex, NULL);
96 }
97 
~Mutex()98 Mutex::~Mutex()
99 {
100 	pthread_mutex_destroy(&mutex);
101 }
102 
Lock()103 void Mutex::Lock()
104 {
105 	pthread_mutex_lock(&mutex);
106 }
107 
Unlock()108 void Mutex::Unlock()
109 {
110 	pthread_mutex_unlock(&mutex);
111 }
112 
TryLock()113 bool Mutex::TryLock()
114 {
115 	return pthread_mutex_trylock(&mutex) == 0;
116 }
117 
Condition()118 Condition::Condition() : Mutex()
119 {
120 	pthread_cond_init(&cond, NULL);
121 }
122 
~Condition()123 Condition::~Condition()
124 {
125 	pthread_cond_destroy(&cond);
126 }
127 
Wakeup()128 void Condition::Wakeup()
129 {
130 	pthread_cond_signal(&cond);
131 }
132 
Wait()133 void Condition::Wait()
134 {
135 	pthread_cond_wait(&cond, &mutex);
136 }
137