Fixed dangling value in mpdm_stat().
[mpdm.git] / mpdm_t.c
blob0d78edfe79da97f33e42d062a127ad4784cb9634
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 static mpdm_t t_new_val(int flags, void *ptr, int size)
53 mpdm_t r = NULL;
55 if (ptr != NULL) {
56 char *ptr2 = malloc(size);
57 memcpy(ptr2, ptr, size);
59 r = mpdm_new(MPDM_FREE | flags, ptr2, size);
62 return r;
66 /**
67 * mpdm_sleep - Sleeps a number of milliseconds.
68 * @msecs: the milliseconds to sleep
70 * Sleeps a number of milliseconds.
71 * [Threading]
73 void mpdm_sleep(int msecs)
75 #ifdef CONFOPT_WIN32
77 Sleep(msecs);
79 #endif
81 #ifdef CONFOPT_NANOSLEEP
82 struct timespec ts;
84 ts.tv_sec = msecs / 1000;
85 ts.tv_nsec = (msecs % 1000) * 1000000;
87 nanosleep(&ts, NULL);
88 #endif
92 /** mutexes **/
94 /**
95 * mpdm_new_mutex - Creates a new mutex.
97 * Creates a new mutex.
98 * [Threading]
100 mpdm_t mpdm_new_mutex(void)
102 mpdm_t r = NULL;
103 char *ptr = NULL;
104 int size = 0;
106 #ifdef CONFOPT_WIN32
107 HANDLE h;
109 h = CreateMutex(NULL, FALSE, NULL);
111 if (h != NULL) {
112 size = sizeof(h);
113 ptr = (char *)&h;
115 #endif
117 #ifdef CONFOPT_PTHREADS
118 pthread_mutex_t m;
120 if (pthread_mutex_init(&m, NULL) == 0) {
121 size = sizeof(m);
122 ptr = (char *)&m;
125 #endif
127 r = t_new_val(0, ptr, size);
129 return r;
134 * mpdm_mutex_lock - Locks a mutex.
135 * @mutex: the mutex to be locked
137 * Locks a mutex. If the mutex is not already locked,
138 * it waits until it is.
139 * [Threading]
141 void mpdm_mutex_lock(mpdm_t mutex)
143 #ifdef CONFOPT_WIN32
144 HANDLE *h = (HANDLE *)mutex->data;
146 WaitForSingleObject(*h, INFINITE);
147 #endif
149 #ifdef CONFOPT_PTHREADS
150 pthread_mutex_t *m = (pthread_mutex_t *)mutex->data;
152 pthread_mutex_lock(m);
153 #endif
158 * mpdm_mutex_unlock - Unlocks a mutex.
159 * @mutex: the mutex to be unlocked
161 * Unlocks a previously locked mutex. The thread
162 * unlocking the mutex must be the one who locked it.
163 * [Threading]
165 void mpdm_mutex_unlock(mpdm_t mutex)
167 #ifdef CONFOPT_WIN32
168 HANDLE *h = (HANDLE *)mutex->data;
170 ReleaseMutex(*h);
171 #endif
173 #ifdef CONFOPT_PTHREADS
174 pthread_mutex_t *m = (pthread_mutex_t *)mutex->data;
176 pthread_mutex_unlock(m);
177 #endif
181 /** semaphores **/
184 * mpdm_new_semaphore - Creates a new semaphore.
185 * @init_value: the initial value of the semaphore.
187 * Creates a new semaphore with an @init_value.
188 * [Threading]
190 mpdm_t mpdm_new_sem(int init_value)
192 char *ptr = NULL;
193 int size = 0;
195 #ifdef CONFOPT_WIN32
196 HANDLE h;
198 if ((h = CreateSemaphore(NULL, init_value, 0x7fffffff, NULL)) != NULL) {
199 size = sizeof(h);
200 ptr = (char *)&h;
203 #endif
205 #ifdef CONFOPT_POSIXSEMS
206 sem_t s;
208 if (sem_init(&s, 0, init_value) == 0) {
209 size = sizeof(s);
210 ptr = (char *)&s;
213 #endif
215 return t_new_val(0, ptr, size);
220 * mpdm_sem_wait - Waits for a semaphore to be ready.
221 * @sem: the semaphore to wait onto
223 * Waits for the value of a semaphore to be > 0. If it's
224 * not, the thread waits until it is.
225 * [Threading]
227 void mpdm_sem_wait(mpdm_t sem)
229 #ifdef CONFOPT_WIN32
230 HANDLE *h = (HANDLE *)sem->data;
232 WaitForSingleObject(*h, INFINITE);
233 #endif
235 #ifdef CONFOPT_POSIXSEMS
236 sem_t *s = (sem_t *)sem->data;
238 sem_wait(s);
239 #endif
244 * mpdm_sem_post - Increments the value of a semaphore.
245 * @sem: the semaphore to increment
247 * Increments by 1 the value of a semaphore.
248 * [Threading]
250 void mpdm_sem_post(mpdm_t sem)
252 #ifdef CONFOPT_WIN32
253 HANDLE *h = (HANDLE *)sem->data;
255 ReleaseSemaphore(*h, 1, NULL);
256 #endif
258 #ifdef CONFOPT_POSIXSEMS
259 sem_t *s = (sem_t *)sem->data;
261 sem_post(s);
262 #endif
266 /** threads **/
268 static void thread_caller(mpdm_t a)
270 /* ignore return value */
271 mpdm_unref(
272 mpdm_ref(
273 mpdm_exec(mpdm_aget(a, 0), mpdm_aget(a, 1), mpdm_aget(a, 2))
277 /* was referenced in mpdm_exec_thread() */
278 mpdm_unref(a);
282 #ifdef CONFOPT_WIN32
283 DWORD WINAPI win32_thread(LPVOID param)
285 thread_caller((mpdm_t) param);
287 return 0;
289 #endif
291 #ifdef CONFOPT_PTHREADS
292 void *pthreads_thread(void *args)
294 thread_caller((mpdm_t) args);
296 return NULL;
298 #endif
301 * mpdm_exec_thread - Runs an executable value in a new thread.
302 * @c: the executable value
303 * @args: executable arguments
304 * @ctxt: the context
306 * Runs the @c executable value in a new thread. The code
307 * starts executing immediately. The @args and @ctxt arguments
308 * are sent to the executable value as arguments.
310 * Returns a handle for the thread.
311 * [Threading]
313 mpdm_t mpdm_exec_thread(mpdm_t c, mpdm_t args, mpdm_t ctxt)
315 mpdm_t a;
316 mpdm_t r = NULL;
317 char *ptr = NULL;
318 int size = 0;
320 if (ctxt == NULL)
321 ctxt = MPDM_A(0);
323 /* to be unreferenced at thread stop */
324 a = mpdm_ref(MPDM_A(3));
326 mpdm_aset(a, c, 0);
327 mpdm_aset(a, args, 1);
328 mpdm_aset(a, ctxt, 2);
330 #ifdef CONFOPT_WIN32
331 HANDLE t;
333 t = CreateThread(NULL, 0, win32_thread, a, 0, NULL);
335 if (t != NULL) {
336 size = sizeof(t);
337 ptr = (char *)&t;
340 #endif
342 #ifdef CONFOPT_PTHREADS
343 pthread_t pt;
345 if (pthread_create(&pt, NULL, pthreads_thread, a) == 0) {
346 size = sizeof(pthread_t);
347 ptr = (char *)&pt;
350 #endif
352 r = t_new_val(0, ptr, size);
354 return r;