Addons updated to new doc format
[io.git] / addons / Thread / source / Thread.c
blob5f50cb20b0c323f586529f57496bfe3f05224f66
1 /*
2 copyright
3 Trevor Fancher, 2006
4 license
5 BSD revised
6 */
9 #include "Thread.h"
11 #ifdef WIN32
12 # include <windows.h>
13 #else
14 # include <pthread.h>
15 # include <unistd.h>
16 #endif
17 #include <stdlib.h>
18 #include "List.h"
20 static List *threads;
21 static ThreadMutex *threads_mutex;
23 static Thread *mainThread;
25 #define LOCK_THEN_UNLOCK(var, code) do { \
26 ThreadMutex_lock(var ## _mutex); \
27 code; \
28 ThreadMutex_unlock(var ## _mutex); \
29 } while(0);
31 ThreadReturnCode Thread_Init(void)
33 #ifdef WIN32
34 HANDLE rawMainThread = GetCurrentThread();
35 #else
36 pthread_t rawMainThread = pthread_self();
37 #endif
39 if (threads)
41 return THREAD_SUCCESS; // already initialized
44 threads = List_new();
45 threads_mutex = ThreadMutex_new();
47 mainThread = Thread_new();
48 if (!mainThread)
50 return THREAD_FAILURE;
53 mainThread->thread = rawMainThread;
54 #ifdef WIN32
55 mainThread->id = GetCurrentThreadId();
56 #endif
58 return THREAD_SUCCESS;
61 void Thread_Shutdown(void)
63 // need to shutdown threads
64 //if (List_size(threads) > 0)
66 if (mainThread)
68 LOCK_THEN_UNLOCK(threads,
69 List_remove_(threads, (void *)mainThread);
71 Thread_destroy(mainThread);
73 else
75 return;
78 LOCK_THEN_UNLOCK(threads,
79 List_free(threads);
82 ThreadMutex_destroy(threads_mutex);
84 mainThread = NULL;
85 threads = NULL;
86 threads_mutex = NULL;
90 Thread *Thread_CurrentThread(void)
92 #ifdef WIN32
93 HANDLE rawCurrentThread = GetCurrentThread();
94 #else
95 pthread_t rawCurrentThread = pthread_self();
96 #endif
97 int isSameThread;
99 Thread *currentThread = NULL;
100 #ifdef WIN32
101 LOCK_THEN_UNLOCK(threads,
102 LIST_FOREACH(threads, index, thread,
103 isSameThread = (((Thread *)thread)->thread == rawCurrentThread);
104 if (isSameThread)
106 currentThread = thread;
107 break;
111 #else
112 LOCK_THEN_UNLOCK(threads,
113 LIST_FOREACH(threads, index, thread,
114 isSameThread = pthread_equal(((Thread *)thread)->thread, rawCurrentThread);
115 if (isSameThread)
117 currentThread = thread;
118 break;
122 #endif
124 if (!currentThread)
126 fflush(stdout);
127 fflush(stderr);
128 fprintf(stderr, "\nYou found a bug in libThread. Please tell trevor on freenode or email trevor@fancher.org.\n");
129 fflush(stderr);
130 exit(EXIT_FAILURE);
133 return currentThread;
136 ThreadReturnCode Thread_WaitOnThread_(Thread *thread)
138 int err;
139 #ifdef WIN32
140 WaitForSingleObject(thread->thread, INFINITE);
141 #else
142 err = pthread_join(thread->thread, NULL);
143 if (err)
145 return THREAD_FAILURE;
147 #endif
148 return THREAD_SUCCESS;
151 List *Thread_Threads(void)
153 return List_clone(threads);
156 Thread *Thread_new(void)
158 Thread *self = malloc(sizeof(Thread));
159 if (self)
161 self->func = NULL;
162 self->funcArg = NULL;
163 self->active = 0;
164 LOCK_THEN_UNLOCK(threads,
165 List_append_(threads, (void *)self);
168 return self;
171 Thread *Thread_newWithFunc_arg_(ThreadFunc func, void *funcArg)
173 Thread *self = Thread_new();
174 if (self)
176 Thread_setFunc_arg_(self, func, funcArg);
178 return self;
181 void Thread_destroy(Thread *self)
183 LOCK_THEN_UNLOCK(threads,
184 List_remove_(threads, (void *)self);
186 free(self);
189 void Thread_setFunc_(Thread *self, ThreadFunc func)
191 self->func = func;
194 void Thread_setFuncArg_(Thread *self, void *funcArg)
196 self->funcArg = funcArg;
199 void Thread_setFunc_arg_(Thread *self, ThreadFunc func, void *funcArg)
201 Thread_setFunc_(self, func);
202 Thread_setFuncArg_(self, funcArg);
205 ThreadReturnCode Thread_start(Thread *self)
207 #ifdef WIN32
208 self->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(self->func), self->funcArg, 0, &(self->id));
209 #else
210 int err;
211 err = pthread_create(&(self->thread), NULL, self->func, self->funcArg);
212 if (err)
214 return THREAD_FAILURE;
216 #endif
218 self->active = 1;
219 return THREAD_SUCCESS;
222 ThreadReturnCode Thread_stop(Thread *self)
224 #ifdef WIN32
225 TerminateThread(self->thread, 0);
226 #else
227 pthread_cancel(self->thread);
228 #endif
230 self->active = 0;
231 return THREAD_SUCCESS;
234 void Thread_exitWithValue_(Thread *self, void *returnValue)
236 self->returnValue = returnValue;
237 #ifdef WIN32
238 ExitThread(0);
239 #else
240 pthread_exit(NULL);
241 #endif
244 ThreadFunc Thread_func(Thread *self)
246 return self->func;
249 void *Thread_funcArg(Thread *self)
251 return self->funcArg;
254 void *Thread_userData(Thread *self)
256 return self->userData;
259 void Thread_setUserData_(Thread *self, void *userData)
261 self->userData = userData;