ecere/gfx/newFonts: Further tweaks for Emscripten
[sdk] / ecere / src / gfx / newFonts / cc / mmthread.h
1 /* *****************************************************************************
2  * Copyright (c) 2007-2014 Alexis Naveros.
3  *
4  * Ecere Corporation has unlimited/unrestricted rights.
5  * *****************************************************************************/
6 /**
7  * @file
8  *
9  * Threading interface, POSIX implementation.
10  */
11
12
13
14 #if defined(COMPILE_FOR_VSL)
15  #define MT_QT
16 #endif
17
18
19
20 #if defined(MT_QT)
21
22  #include "mmthreadqt.h"
23
24 #elif defined(MT_DISABLED)
25
26 struct mtNull
27 {
28 };
29
30 typedef struct mtNull mtMutex;
31 typedef struct mtNull mtSpin;
32 typedef struct mtNull mtSignal;
33
34  #define mtMutexInit(a)
35  #define mtMutexDestroy(a)
36  #define mtMutexLock(a)
37  #define mtMutexUnlock(a)
38  #define mtMutexTryLock(a)
39
40  #define mtSpinInit(a)
41  #define mtSpinDestroy(a)
42  #define mtSpinLock(a)
43  #define mtSpinUnlock(a)
44  #define mtSpinTryLock(a)
45
46  #define mtSignalInit(a)
47  #define mtSignalDestroy(a)
48  #define mtSignalDispatch(a)
49  #define mtSignalBroadcast(a)
50  #define mtSignalMutexWait(a,b)
51
52 #else
53
54  #include <pthread.h>
55  #include <unistd.h>
56  #include <sched.h>
57  #include <limits.h>
58
59  #if _POSIX_SPIN_LOCKS > 0
60   #define MT_SPIN_LOCK_SUPPORT
61  #endif
62 /*
63  #define MT_BARRIER_SUPPORT
64  #define MT_RWLOCK_SUPPORT
65 */
66
67
68 static inline void mtYield()
69 {
70   sched_yield();
71   return;
72 }
73
74
75 typedef struct mtThread mtThread;
76
77 struct mtThread
78 {
79   pthread_t pthread;
80 };
81
82
83 #define MT_THREAD_FLAGS_JOINABLE (0x1)
84 #define MT_THREAD_FLAGS_SETSTACK (0x2)
85
86
87 static inline void mtThreadCreate( mtThread *thread, void *(*threadmain)( void *value ), void *value, int flags, void *stack, size_t stacksize )
88 {
89   pthread_attr_t attr;
90
91   pthread_attr_init( &attr );
92 #if !MM_WIN32 && !MM_WIN64
93   if( flags & MT_THREAD_FLAGS_SETSTACK )
94     pthread_attr_setstack( &attr, stack, stacksize );
95 #endif
96   if( flags & MT_THREAD_FLAGS_JOINABLE )
97     pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
98   else
99     pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
100   pthread_create( &thread->pthread, &attr, threadmain, value );
101   pthread_attr_destroy( &attr );
102
103   return;
104 }
105
106 static inline void mtThreadExit()
107 {
108   pthread_exit( 0 );
109   return;
110 }
111
112 static inline void mtThreadJoin( mtThread *thread )
113 {
114   void *ret;
115   pthread_join( thread->pthread, &ret );
116   return;
117 }
118
119
120 static inline mtThread mtThreadSelf()
121 {
122   mtThread thread;
123   thread.pthread = pthread_self();
124   return thread;
125 }
126
127 static inline int mtThreadCmpEqual( mtThread *thread0, mtThread *thread1 )
128 {
129   return ( pthread_equal( thread0->pthread, thread1->pthread ) != 0 ? 1 : 0 );
130 }
131
132
133 static inline size_t mtGetMinimumStackSize()
134 {
135  #ifdef PTHREAD_STACK_MIN
136   return PTHREAD_STACK_MIN;
137  #else
138   return ( mmcontext.pagesize ? 4*mmcontext.pagesize : 16384 );
139  #endif
140 }
141
142
143
144  #ifdef MT_DEBUG
145   #ifndef DEBUG_WARNING()
146    #define DEBUG_WARNING() ({printf( "\nRF WARNING : %s %s %d\n", __FILE__, __FUNCTION__, __LINE__ ); fflush( stdout );})
147   #endif
148  #endif
149
150
151
152 typedef struct mtMutex mtMutex;
153
154 struct mtMutex
155 {
156 #ifdef MT_DEBUG
157   unsigned char *function;
158   unsigned char *file;
159   int line;
160 #endif
161   pthread_mutex_t pmutex;
162 };
163
164 static inline void mtMutexInit( mtMutex *mutex )
165 {
166   pthread_mutex_init( &mutex->pmutex, 0 );
167   return;
168 }
169
170 static inline void mtMutexDestroy( mtMutex *mutex )
171 {
172   pthread_mutex_destroy( &mutex->pmutex );
173   return;
174 }
175
176  #ifdef MT_DEBUG
177
178   #define mtMutexLock(a) mtMutexLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
179   #define mtMutexUnlock(a) mtMutexUnlockDebug(a,__FUNCTION__,__FILE__,__LINE__)
180   #define mtMutexTryLock(a) mtMutexTryLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
181
182 static inline void mtMutexLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
183 {
184   printf( "Mutex lock :    Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
185   fflush( stdout );
186   if( pthread_mutex_trylock( &mutex->pmutex ) )
187   {
188     printf( "    Mutex %p locked by %s() in %s:%d\n", mutex, mutex->function, mutex->file, mutex->line );
189     fflush( stdout );
190     if( pthread_mutex_lock( &mutex->pmutex ) )
191       DEBUG_WARNING();
192   }
193   mutex->function = (unsigned char *)function;
194   mutex->file = (unsigned char *)file;
195   mutex->line = line;
196   return;
197 }
198
199 static inline void mtMutexUnlockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
200 {
201   mutex->function = (unsigned char *)function;
202   mutex->file = (unsigned char *)file;
203   mutex->line = line;
204   printf( "Mutex Unlock :  Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
205   fflush( stdout );
206   if( pthread_mutex_unlock( &mutex->pmutex ) )
207     DEBUG_WARNING();
208   return;
209 }
210
211 static inline int mtMutexTryLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
212 {
213   printf( "Mutex Trylock :  Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
214   fflush( stdout );
215   if( !( pthread_mutex_trylock( &mutex->pmutex ) ) )
216   {
217     mutex->function = (unsigned char *)function;
218     mutex->file = (unsigned char *)file;
219     mutex->line = line;
220     return 1;
221   }
222   else
223     return 0;
224 }
225
226  #else
227
228 static inline void mtMutexLock( mtMutex *mutex )
229 {
230   pthread_mutex_lock( &mutex->pmutex );
231   return;
232 }
233
234 static inline void mtMutexUnlock( mtMutex *mutex )
235 {
236   pthread_mutex_unlock( &mutex->pmutex );
237   return;
238 }
239
240 static inline int mtMutexTryLock( mtMutex *mutex )
241 {
242   return !( pthread_mutex_trylock( &mutex->pmutex ) );
243 }
244
245  #endif
246
247
248
249 ////
250
251
252
253 typedef struct mtSignal mtSignal;
254
255 struct mtSignal
256 {
257   pthread_cond_t pcond;
258 };
259
260 static inline void mtSignalInit( mtSignal *signal )
261 {
262   pthread_cond_init( &signal->pcond, 0 );
263   return;
264 }
265
266 static inline void mtSignalDestroy( mtSignal *signal )
267 {
268   pthread_cond_destroy( &signal->pcond );
269   return;
270 }
271
272 static inline void mtSignalWake( mtSignal *signal )
273 {
274  #ifdef MT_DEBUG
275   if( pthread_cond_signal( &signal->pcond ) )
276     DEBUG_WARNING();
277  #else
278   pthread_cond_signal( &signal->pcond );
279  #endif
280   return;
281 }
282
283 static inline void mtSignalBroadcast( mtSignal *signal )
284 {
285  #ifdef MT_DEBUG
286   if( pthread_cond_broadcast( &signal->pcond ) )
287     DEBUG_WARNING();
288  #else
289   pthread_cond_broadcast( &signal->pcond );
290  #endif
291   return;
292 }
293
294 static inline void mtSignalWait( mtSignal *signal, mtMutex *mutex )
295 {
296  #ifdef MT_DEBUG
297   if( pthread_cond_wait( &signal->pcond, &mutex->pmutex ) )
298     DEBUG_WARNING();
299  #else
300   pthread_cond_wait( &signal->pcond, &mutex->pmutex );
301  #endif
302   return;
303 }
304
305 static inline void mtSignalWaitTimeout( mtSignal *signal, mtMutex *mutex, long milliseconds )
306 {
307   uint64_t microsecs;
308   struct timespec ts;
309   struct timeval tp;
310   gettimeofday( &tp, NULL );
311   ts.tv_sec  = tp.tv_sec + ( milliseconds / 1000 );
312   microsecs = tp.tv_usec + ( ( milliseconds % 1000 ) * 1000 );
313   if( microsecs >= 1000000 )
314   {
315     ts.tv_sec++;
316     microsecs -= 1000000;
317   }
318   ts.tv_nsec = (int)(microsecs * 1000);
319   pthread_cond_timedwait( &signal->pcond, &mutex->pmutex, &ts );
320   return;
321 }
322
323  #ifdef MT_DEBUG
324   #define MT_MUTEX_INITIALIZER { 0, 0, 0, PTHREAD_MUTEX_INITIALIZER }
325  #else
326   #define MT_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
327  #endif
328
329
330
331 ////
332
333
334
335  #ifdef MM_ATOMIC_SUPPORT
336
337 typedef struct mtSpin mtSpin;
338
339 struct mtSpin
340 {
341   mmAtomic32 atomicspin;
342 };
343
344 static inline void mtSpinInit( mtSpin *spin )
345 {
346   mmAtomicWrite32( &spin->atomicspin, 0x0 );
347   return;
348 }
349
350 static inline void mtSpinDestroy( mtSpin *spin )
351 {
352   return;
353 }
354
355 static inline void mtSpinLock( mtSpin *spin )
356 {
357   mmAtomicSpin32( &spin->atomicspin, 0x0, 0x1 );
358   return;
359 }
360
361 static inline void mtSpinUnlock( mtSpin *spin )
362 {
363   mmAtomicWrite32( &spin->atomicspin, 0x0 );
364   return;
365 }
366
367 static inline int mtSpinTryLock( mtSpin *spin )
368 {
369   return mmAtomicCmpReplace32( &spin->atomicspin, 0x0, 0x1 );
370 }
371
372  #elif _POSIX_SPIN_LOCKS > 0
373
374 typedef struct mtSpin mtSpin;
375
376 struct mtSpin
377 {
378  #ifdef MT_DEBUG
379   unsigned char *function;
380   unsigned char *file;
381   int line;
382  #endif
383   pthread_spinlock_t pspinlock;
384 };
385
386 static inline void mtSpinInit( mtSpin *spin )
387 {
388   pthread_spin_init( &spin->pspinlock, PTHREAD_PROCESS_PRIVATE );
389   return;
390 }
391
392 static inline void mtSpinDestroy( mtSpin *spin )
393 {
394   pthread_spin_destroy( &spin->pspinlock );
395   return;
396 }
397
398 static inline void mtSpinLock( mtSpin *spin )
399 {
400   #ifdef MT_DEBUG
401   if( pthread_spin_lock( &spin->pspinlock ) )
402     DEBUG_WARNING();
403   #else
404   pthread_spin_lock( &spin->pspinlock );
405   #endif
406   return;
407 }
408
409 static inline void mtSpinUnlock( mtSpin *spin )
410 {
411   #ifdef MT_DEBUG
412   if( pthread_spin_unlock( &spin->pspinlock ) )
413     DEBUG_WARNING();
414   #else
415   pthread_spin_unlock( &spin->pspinlock );
416   #endif
417   return;
418 }
419
420 static inline int mtSpinTryLock( mtSpin *spin )
421 {
422   return !( pthread_spin_trylock( &spin->pspinlock ) );
423 }
424
425  #else
426
427 typedef struct mtMutex mtSpin;
428
429   #define mtSpinInit(a) mtMutexInit(a)
430   #define mtSpinDestroy(a) mtMutexDestroy(a)
431   #define mtSpinLock(a) mtMutexLock(a)
432   #define mtSpinUnlock(a) mtMutexUnlock(a)
433   #define mtSpinTryLock(a) mtMutexTryLock(a)
434
435  #endif
436
437
438
439 ////
440
441
442
443  #ifdef MT_BARRIER_SUPPORT
444
445 typedef struct
446 {
447   pthread_barrier_t pbarrier;
448 } mtBarrier;
449
450 static inline void mtBarrierInit( mtBarrier *barrier, int count )
451 {
452   pthread_barrier_init( &barrier->pbarrier, 0, count );
453   return;
454 }
455
456 static inline void mtBarrierDestroy( mtBarrier *barrier )
457 {
458   pthread_barrier_destroy( &barrier->pbarrier );
459   return;
460 }
461
462 static inline int mtBarrierWait( mtBarrier *barrier )
463 {
464   return pthread_barrier_wait( &barrier->pbarrier );
465 }
466
467  #endif
468
469
470
471 ////
472
473
474
475  #ifdef MT_RWLOCK_SUPPORT
476
477 typedef struct mtRWlock mtRWlock;
478
479 struct mtRWlock
480 {
481   pthread_rwlock_t prwlock;
482 };
483
484
485 static inline void mtRWlockInit( mtRWlock *rwlock )
486 {
487   pthread_rwlock_init( &rwlock->prwlock, 0 );
488   return;
489 }
490
491 static inline void mtRWlockDestroy( mtRWlock *rwlock )
492 {
493   pthread_rwlock_destroy( &rwlock->prwlock );
494   return;
495 }
496
497 static inline void mtRWlockRead( mtRWlock *rwlock )
498 {
499   pthread_rwlock_rdlock( &rwlock->prwlock );
500   return;
501 }
502
503 static inline void mtRWlockWrite( mtRWlock *rwlock )
504 {
505   pthread_rwlock_wrlock( &rwlock->prwlock );
506   return;
507 }
508
509 static inline void mtRWlockUnlock( mtRWlock *rwlock )
510 {
511   pthread_rwlock_unlock( &rwlock->prwlock );
512   return;
513 }
514
515 static inline int mtRWlockTryRead( mtRWlock *rwlock )
516 {
517   return pthread_rwlock_rdlock( &rwlock->prwlock );
518 }
519
520 static inline int mtRWlockTryWrite( mtRWlock *rwlock )
521 {
522   return pthread_rwlock_wrlock( &rwlock->prwlock );
523 }
524
525  #endif
526
527
528 #endif
529
530