ecere/gfx/NewFonts: Emscripten fixes
[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 #if !defined(__EMSCRIPTEN__)
389   pthread_spin_init( &spin->pspinlock, PTHREAD_PROCESS_PRIVATE );
390 #endif
391   return;
392 }
393
394 static inline void mtSpinDestroy( mtSpin *spin )
395 {
396 #if !defined(__EMSCRIPTEN__)
397   pthread_spin_destroy( &spin->pspinlock );
398 #endif
399   return;
400 }
401
402 static inline void mtSpinLock( mtSpin *spin )
403 {
404 #if !defined(__EMSCRIPTEN__)
405   #ifdef MT_DEBUG
406   if( pthread_spin_lock( &spin->pspinlock ) )
407     DEBUG_WARNING();
408   #else
409   pthread_spin_lock( &spin->pspinlock );
410   #endif
411 #endif
412   return;
413 }
414
415 static inline void mtSpinUnlock( mtSpin *spin )
416 {
417 #if !defined(__EMSCRIPTEN__)
418   #ifdef MT_DEBUG
419   if( pthread_spin_unlock( &spin->pspinlock ) )
420     DEBUG_WARNING();
421   #else
422   pthread_spin_unlock( &spin->pspinlock );
423   #endif
424 #endif
425   return;
426 }
427
428 static inline int mtSpinTryLock( mtSpin *spin )
429 {
430 #if !defined(__EMSCRIPTEN__)
431   return !( pthread_spin_trylock( &spin->pspinlock ) );
432 #else
433   return 0;
434 #endif
435 }
436
437  #else
438
439 typedef struct mtMutex mtSpin;
440
441   #define mtSpinInit(a) mtMutexInit(a)
442   #define mtSpinDestroy(a) mtMutexDestroy(a)
443   #define mtSpinLock(a) mtMutexLock(a)
444   #define mtSpinUnlock(a) mtMutexUnlock(a)
445   #define mtSpinTryLock(a) mtMutexTryLock(a)
446
447  #endif
448
449
450
451 ////
452
453
454
455  #ifdef MT_BARRIER_SUPPORT
456
457 typedef struct
458 {
459   pthread_barrier_t pbarrier;
460 } mtBarrier;
461
462 static inline void mtBarrierInit( mtBarrier *barrier, int count )
463 {
464 #if !defined(__EMSCRIPTEN__)
465   pthread_barrier_init( &barrier->pbarrier, 0, count );
466 #endif
467   return;
468 }
469
470 static inline void mtBarrierDestroy( mtBarrier *barrier )
471 {
472 #if !defined(__EMSCRIPTEN__)
473   pthread_barrier_destroy( &barrier->pbarrier );
474 #endif
475   return;
476 }
477
478 static inline int mtBarrierWait( mtBarrier *barrier )
479 {
480 #if !defined(__EMSCRIPTEN__)
481   return pthread_barrier_wait( &barrier->pbarrier );
482 #else
483   return 0;
484 #endif
485 }
486
487  #endif
488
489
490
491 ////
492
493
494
495  #ifdef MT_RWLOCK_SUPPORT
496
497 typedef struct mtRWlock mtRWlock;
498
499 struct mtRWlock
500 {
501   pthread_rwlock_t prwlock;
502 };
503
504
505 static inline void mtRWlockInit( mtRWlock *rwlock )
506 {
507 #if !defined(__EMSCRIPTEN__)
508   pthread_rwlock_init( &rwlock->prwlock, 0 );
509 #endif
510   return;
511 }
512
513 static inline void mtRWlockDestroy( mtRWlock *rwlock )
514 {
515 #if !defined(__EMSCRIPTEN__)
516   pthread_rwlock_destroy( &rwlock->prwlock );
517 #endif
518   return;
519 }
520
521 static inline void mtRWlockRead( mtRWlock *rwlock )
522 {
523 #if !defined(__EMSCRIPTEN__)
524   pthread_rwlock_rdlock( &rwlock->prwlock );
525 #endif
526   return;
527 }
528
529 static inline void mtRWlockWrite( mtRWlock *rwlock )
530 {
531 #if !defined(__EMSCRIPTEN__)
532   pthread_rwlock_wrlock( &rwlock->prwlock );
533 #endif
534   return;
535 }
536
537 static inline void mtRWlockUnlock( mtRWlock *rwlock )
538 {
539 #if !defined(__EMSCRIPTEN__)
540   pthread_rwlock_unlock( &rwlock->prwlock );
541 #endif
542   return;
543 }
544
545 static inline int mtRWlockTryRead( mtRWlock *rwlock )
546 {
547 #if !defined(__EMSCRIPTEN__)
548   return pthread_rwlock_rdlock( &rwlock->prwlock );
549 #else
550   return 0;
551 #endif
552 }
553
554 static inline int mtRWlockTryWrite( mtRWlock *rwlock )
555 {
556 #if !defined(__EMSCRIPTEN__)
557   return pthread_rwlock_wrlock( &rwlock->prwlock );
558 #else
559   return 0;
560 #endif
561 }
562
563  #endif
564
565
566 #endif
567
568