Added new flags for mutexes, semaphores and threads.
[mpdm.git] / mpdm_t.c
blobd142a5292c6be96cead47c609fe98ce00bd504a7
1 /*
3 MPDM - Minimum Profit Data Manager
4 Copyright (C) 2003/2010 Angel Ortega <angel@triptico.com>
6 mpdm_t.c - Threading primitives
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <locale.h>
32 #include <time.h>
34 #ifdef CONFOPT_WIN32
35 #include <windows.h>
36 #endif
38 #ifdef CONFOPT_PTHREADS
39 #include <pthread.h>
40 #endif
42 #ifdef CONFOPT_POSIXSEMS
43 #include <semaphore.h>
44 #endif
46 #include "mpdm.h"
49 /** code **/
51 /**
52 * mpdm_sleep - Sleeps a number of milliseconds.
53 * @msecs: the milliseconds to sleep
55 * Sleeps a number of milliseconds.
56 * [Threading]
58 void mpdm_sleep(int msecs)
60 #ifdef CONFOPT_WIN32
62 Sleep(msecs);
64 #endif
66 #ifdef CONFOPT_NANOSLEEP
67 struct timespec ts;
69 ts.tv_sec = msecs / 1000;
70 ts.tv_nsec = (msecs % 1000) * 1000000;
72 nanosleep(&ts, NULL);
73 #endif
77 /** mutexes **/
79 /**
80 * mpdm_new_mutex - Creates a new mutex.
82 * Creates a new mutex.
83 * [Threading]
85 mpdm_t mpdm_new_mutex(void)
87 mpdm_t r = NULL;
88 char *ptr = NULL;
89 int size = 0;
91 #ifdef CONFOPT_WIN32
92 HANDLE h;
94 h = CreateMutex(NULL, FALSE, NULL);
96 if (h != NULL) {
97 size = sizeof(h);
98 ptr = (char *)&h;
100 #endif
102 #ifdef CONFOPT_PTHREADS
103 pthread_mutex_t m;
105 if (pthread_mutex_init(&m, NULL) == 0) {
106 size = sizeof(m);
107 ptr = (char *)&m;
110 #endif
112 r = MPDM_C(MPDM_MUTEX, ptr, size);
114 return r;
119 * mpdm_mutex_lock - Locks a mutex.
120 * @mutex: the mutex to be locked
122 * Locks a mutex. If the mutex is not already locked,
123 * it waits until it is.
124 * [Threading]
126 void mpdm_mutex_lock(mpdm_t mutex)
128 #ifdef CONFOPT_WIN32
129 HANDLE *h = (HANDLE *)mutex->data;
131 WaitForSingleObject(*h, INFINITE);
132 #endif
134 #ifdef CONFOPT_PTHREADS
135 pthread_mutex_t *m = (pthread_mutex_t *)mutex->data;
137 pthread_mutex_lock(m);
138 #endif
143 * mpdm_mutex_unlock - Unlocks a mutex.
144 * @mutex: the mutex to be unlocked
146 * Unlocks a previously locked mutex. The thread
147 * unlocking the mutex must be the one who locked it.
148 * [Threading]
150 void mpdm_mutex_unlock(mpdm_t mutex)
152 #ifdef CONFOPT_WIN32
153 HANDLE *h = (HANDLE *)mutex->data;
155 ReleaseMutex(*h);
156 #endif
158 #ifdef CONFOPT_PTHREADS
159 pthread_mutex_t *m = (pthread_mutex_t *)mutex->data;
161 pthread_mutex_unlock(m);
162 #endif
166 /** semaphores **/
169 * mpdm_new_semaphore - Creates a new semaphore.
170 * @init_value: the initial value of the semaphore.
172 * Creates a new semaphore with an @init_value.
173 * [Threading]
175 mpdm_t mpdm_new_sem(int init_value)
177 char *ptr = NULL;
178 int size = 0;
180 #ifdef CONFOPT_WIN32
181 HANDLE h;
183 if ((h = CreateSemaphore(NULL, init_value, 0x7fffffff, NULL)) != NULL) {
184 size = sizeof(h);
185 ptr = (char *)&h;
188 #endif
190 #ifdef CONFOPT_POSIXSEMS
191 sem_t s;
193 if (sem_init(&s, 0, init_value) == 0) {
194 size = sizeof(s);
195 ptr = (char *)&s;
198 #endif
200 return MPDM_C(MPDM_SEMAPHORE, ptr, size);
205 * mpdm_sem_wait - Waits for a semaphore to be ready.
206 * @sem: the semaphore to wait onto
208 * Waits for the value of a semaphore to be > 0. If it's
209 * not, the thread waits until it is.
210 * [Threading]
212 void mpdm_sem_wait(mpdm_t sem)
214 #ifdef CONFOPT_WIN32
215 HANDLE *h = (HANDLE *)sem->data;
217 WaitForSingleObject(*h, INFINITE);
218 #endif
220 #ifdef CONFOPT_POSIXSEMS
221 sem_t *s = (sem_t *)sem->data;
223 sem_wait(s);
224 #endif
229 * mpdm_sem_post - Increments the value of a semaphore.
230 * @sem: the semaphore to increment
232 * Increments by 1 the value of a semaphore.
233 * [Threading]
235 void mpdm_sem_post(mpdm_t sem)
237 #ifdef CONFOPT_WIN32
238 HANDLE *h = (HANDLE *)sem->data;
240 ReleaseSemaphore(*h, 1, NULL);
241 #endif
243 #ifdef CONFOPT_POSIXSEMS
244 sem_t *s = (sem_t *)sem->data;
246 sem_post(s);
247 #endif
251 /** threads **/
253 static void thread_caller(mpdm_t a)
255 /* ignore return value */
256 mpdm_unref(
257 mpdm_ref(
258 mpdm_exec(mpdm_aget(a, 0), mpdm_aget(a, 1), mpdm_aget(a, 2))
262 /* was referenced in mpdm_exec_thread() */
263 mpdm_unref(a);
267 #ifdef CONFOPT_WIN32
268 DWORD WINAPI win32_thread(LPVOID param)
270 thread_caller((mpdm_t) param);
272 return 0;
274 #endif
276 #ifdef CONFOPT_PTHREADS
277 void *pthreads_thread(void *args)
279 thread_caller((mpdm_t) args);
281 return NULL;
283 #endif
286 * mpdm_exec_thread - Runs an executable value in a new thread.
287 * @c: the executable value
288 * @args: executable arguments
289 * @ctxt: the context
291 * Runs the @c executable value in a new thread. The code
292 * starts executing immediately. The @args and @ctxt arguments
293 * are sent to the executable value as arguments.
295 * Returns a handle for the thread.
296 * [Threading]
298 mpdm_t mpdm_exec_thread(mpdm_t c, mpdm_t args, mpdm_t ctxt)
300 mpdm_t a;
301 mpdm_t r = NULL;
302 char *ptr = NULL;
303 int size = 0;
305 if (ctxt == NULL)
306 ctxt = MPDM_A(0);
308 /* to be unreferenced at thread stop */
309 a = mpdm_ref(MPDM_A(3));
311 mpdm_aset(a, c, 0);
312 mpdm_aset(a, args, 1);
313 mpdm_aset(a, ctxt, 2);
315 #ifdef CONFOPT_WIN32
316 HANDLE t;
318 t = CreateThread(NULL, 0, win32_thread, a, 0, NULL);
320 if (t != NULL) {
321 size = sizeof(t);
322 ptr = (char *)&t;
325 #endif
327 #ifdef CONFOPT_PTHREADS
328 pthread_t pt;
330 if (pthread_create(&pt, NULL, pthreads_thread, a) == 0) {
331 size = sizeof(pthread_t);
332 ptr = (char *)&pt;
335 #endif
337 r = MPDM_C(MPDM_THREAD, ptr, size);
339 return r;