cfl_platform.cpp
Go to the documentation of this file.
1 /** @file cfl_platform.cpp Platform dependant wrappers */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2013, 2024 Thomas Moor
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 
23 
24 // My header
25 #include "cfl_definitions.h"
26 #include "cfl_platform.h"
27 
28 // Extra header
29 #include <signal.h>
30 #include <exception>
31 #include <ostream>
32 
33 #ifdef FAUDES_GENERIC
34 void faudes_invalid(const std::string& msg) {
35  std::cerr << "faudes_invalid(): " << msg << std:endl;
36  throw 0;
37 }
38 #endif
39 
40 
41 // Path separator (statics, see faudes_pathsep)
42 #ifdef FAUDES_POSIX
43 const std::string& faudes_pathseps(void) {
44  static std::string faudes_pathsep_str = "/";
45  return faudes_pathsep_str;
46 }
47 const std::string& faudes_pathsep(void) {
48  return faudes_pathseps();
49 }
50 #endif
51 #ifdef FAUDES_GENERIC
52 const std::string& faudes_pathseps(void) {
53  static std::string faudes_pathsep_str = "/";
54  return faudes_pathsep_str;
55 }
56 const std::string& faudes_pathsep(void) {
57  return faudes_pathseps();
58 }
59 #endif
60 #ifdef FAUDES_WINDOWS
61 const std::string& faudes_pathseps(void) {
62  static std::string faudes_pathseps_str = "\\:/";
63  return faudes_pathseps_str;
64 }
65 const std::string& faudes_pathsep(void) {
66  static std::string faudes_pathsep_str = "";
67  if(faudes_pathsep_str=="")
68  faudes_pathsep_str=faudes_pathseps().substr(0,1);
69  return faudes_pathsep_str;
70 }
71 #endif
72 
73 
74 
75 // Uniform signalhandler on termination
76 void faudes_termsignal(void (*sighandler)(int)) {
77 #ifdef SIGTERM
78  signal(SIGTERM, sighandler);
79 #endif
80 #ifdef SIGINT
81  signal(SIGINT, sighandler);
82 #endif
83 #ifdef SIGQUIT
84  signal(SIGQUIT, sighandler);
85 #endif
86 #ifdef SIGHUP
87  signal(SIGHUP, sighandler);
88 #endif
89 #ifdef SIGABRT
90  signal(SIGABRT, sighandler);
91 #endif
92 }
93 
94 // Uniform signal names for POSIX / Windows/MinGW (see e.g. simfaudes.cpp)
95 const char* faudes_strsignal(int sig) {
96 #ifdef FAUDES_POSIX
97  return strsignal(sig);
98 #endif
99 #ifdef FAUDES_WINDOWS
100  return "unknown";
101 #endif
102 }
103 
104 // Uniform sleep for POSIX/Windows (see e.g. iodevice plug-in)
105 #ifdef FAUDES_POSIX
106 void faudes_sleep(long int sec) {sleep(sec);}
107 void faudes_usleep(long int usec) {usleep(usec);}
108 #endif
109 #ifdef FAUDES_WINDOWS
110 void faudes_sleep(long int sec) {Sleep((sec) * 1000);}
111 void faudes_usleep(long int usec) {Sleep((usec) / 1000);}
112 #endif
113 #ifdef FAUDES_GENERIC
114 void faudes_sleep(long int sec) { faudes_invalid("faudes_sleep()"); }
115 void faudes_usleep(long int usec) { faudes_invalid("faudes_usleep()"); }
116 #endif
117 
118 
119 
120 #ifdef FAUDES_SYSTIME
121 
122 // static debugging timer
123 faudes_systime_t gPerfTimer1;
124 
125 // Uniform system time (using pthread timespec semantics, trust MinGW to provide)
126 #if defined(FAUDES_POSIX)
127 void faudes_gettimeofday(faudes_systime_t* now) {
128  timeval nowval;
129  gettimeofday(&nowval,0);
130  now->tv_sec=nowval.tv_sec;
131  now->tv_nsec=nowval.tv_usec * 1000;
132 }
133 #endif
134 
135 #if defined(FAUDES_WINDOWS)
136 void faudes_gettimeofday(faudes_systime_t* now) {
137  DWORD nowval;
138  nowval= timeGetTime();
139  now->tv_sec=nowval / 1000;
140  now->tv_nsec=(nowval % 1000) *1000000;
141 }
142 #endif
143 
144 
145 
146 // Uniform system time (supporting functions)
147 void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_systime_t* res) {
148  res->tv_sec = end.tv_sec-begin.tv_sec;
149  res->tv_nsec = end.tv_nsec-begin.tv_nsec;
150  if(res->tv_nsec <= 0){
151  res->tv_sec--;
152  res->tv_nsec += 1000000000;
153  }
154 }
155 
156 // Uniform system time (supporting functions)
157 void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_mstime_t* res) {
158  *res = 1000*( end.tv_sec-begin.tv_sec);
159  *res += (end.tv_nsec-begin.tv_nsec) / 1000000;
160 }
161 
162 // Uniform system time (supporting functions)
163 void faudes_sumsystime(const faudes_systime_t& begin, const faudes_systime_t& duration, faudes_systime_t* res) {
164  res->tv_sec = begin.tv_sec + duration.tv_sec;
165  res->tv_nsec = begin.tv_nsec + duration.tv_nsec;
166  if(res->tv_nsec >= 1000000000) {
167  res->tv_sec++;
168  res->tv_nsec-=1000000000;
169  }
170 }
171 
172 // Uniform system time (supporting functions)
173 void faudes_msdelay(faudes_mstime_t msecs,faudes_systime_t* end) {
174  faudes_systime_t now;
175  faudes_gettimeofday(&now);
176  faudes_systime_t delta;
177  delta.tv_sec = msecs/1000;
178  delta.tv_nsec = (msecs % 1000) *1000000;
179  faudes_sumsystime(now,delta,end);
180 }
181 
182 // Uniform system time (supporting functions)
183 void faudes_usdelay(faudes_mstime_t usecs,faudes_systime_t* end) {
184  faudes_systime_t now;
185  faudes_gettimeofday(&now);
186  faudes_systime_t delta;
187  delta.tv_sec = usecs/1000000;
188  delta.tv_nsec = (usecs % 1000000) * 1000;
189  faudes_sumsystime(now,delta,end);
190 }
191 
192 
193 #endif // systime
194 
195 
196 #ifdef FAUDES_NETWORK
197 
198 #ifdef FAUDES_POSIX
199 int faudes_closesocket(int fd) {
200  return close(fd);
201 }
202 int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
203  return setsockopt(fd,level,optname,optval,optlen);
204 }
205 int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
206  return getsockopt(fd,level,optname,optval,optlen);
207 }
208 int faudes_getsocket_error(int fd) {
209  int opt=0;
210  socklen_t len = sizeof(opt);
211  int res = getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &len) < 0 ? -1 : 0;
212  if(opt!=0) res=-1;
213  return res;
214 }
215 int faudes_setsocket_nonblocking(int fd, bool noblo) {
216  int sopt=fcntl(fd, F_GETFL, NULL);
217  if(sopt<0) return -1; // error
218  if(noblo) {
219  int rc=fcntl(fd, F_SETFL, sopt|O_NONBLOCK);
220  return rc < 0 ? -1 : 0;
221  } else {
222  int rc=fcntl(fd, F_SETFL, sopt& (~O_NONBLOCK));
223  return rc < 0 ? -1 : 0;
224  }
225 }
226 #endif
227 #ifdef FAUDES_WINDOWS
228 typedef int socklen_t;
229 int faudes_closesocket(int fd) {
230  return closesocket(fd);
231 }
232 int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
233  return setsockopt(fd,level,optname,(char*) optval,optlen);
234 }
235 int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
236  return getsockopt(fd,level,optname,(char*) optval,optlen);
237 }
238 int faudes_getsocket_error(int fd) {
239  int opt=0;
240  socklen_t len = sizeof(opt);
241  int res = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 ? -1 : 0;
242  if(opt!=0) res=-1;
243  return res;
244 }
245 int faudes_setsocket_nonblocking(int fd, bool noblo) {
246  unsigned long onoff=0;
247  if(noblo) onoff=1;
248  return ioctlsocket(fd, FIONBIO, &onoff) == SOCKET_ERROR ? -1 : 0;
249 }
250 #endif
251 #ifdef FAUDES_GENERIC
252 #error option network not available on generic platform
253 #endif
254 
255 #endif // network
256 
257 
258 
259 // straight PPOSIX threads (aka plain wrappers)
260 #ifdef FAUDES_THREADS
261 #ifdef FAUDES_POSIX
262 // Thread data type (use plain POSIX thread)
263 typedef pthread_t faudes_thread_t;
264 // Thread functions (plain pthread wrapper)
265 int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg){
266  // prepare attribute for plain joinable thread
267  pthread_attr_t attr;
268  pthread_attr_init(&attr);
269  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
270  // start execute
271  int ret = pthread_create(thr, &attr, fnct, arg);
272  // done
273  pthread_attr_destroy(&attr);
274  return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
275 }
276 faudes_thread_t faudes_thread_current(void) {
277  return pthread_self();
278 }
279 int faudes_thread_detach(faudes_thread_t thr) {
280  return pthread_detach(thr)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
281 }
282 int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1) {
283  return pthread_equal(thr0, thr1);
284 }
285 void faudes_thread_exit(void* res) {
286  pthread_exit(res);
287 }
288 int faudes_thread_join(faudes_thread_t thr, void **res) {
289  return pthread_join(thr, res) == 0 ? FAUDES_THREAD_ERROR : FAUDES_THREAD_SUCCESS;
290 }
291 #endif
292 #endif // POSIX threads
293 
294 // Windows to mimique PPOSIX threads
295 #ifdef FAUDES_THREADS
296 #ifdef FAUDES_WINDOWS
297 
298 // Use Windows thread local storage to implement pointer-typed return values
299 DWORD faudes_thread_tlsidx=TLS_OUT_OF_INDEXES;
300 
301 // Windows thread function wrapper with faudes_thread_t argument;
302 static unsigned WINAPI faudes_thread_wrapper(void *argfth) {
303  // access my thread struct
304  faudes_thread_t fthread = (faudes_thread_t) argfth;
305  // record my thread struct as tls
306  TlsSetValue(faudes_thread_tlsidx,fthread);
307  // extract actual function and arguments
308  void *(*fnct)(void*) = fthread->mFnct;
309  void *arg = fthread->mArg;
310  // call function
311  void* res = fnct(arg);
312  // uniform exit to retrieve return value
313  faudes_thread_exit(res);
314  // return dummy
315  return 0;
316 }
317 
318 // Thread functions (Windows to mimic pthreads)
319 int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg){
320  // initialize thread local storage block
321  if(faudes_thread_tlsidx==TLS_OUT_OF_INDEXES)
322  faudes_thread_tlsidx=TlsAlloc();
323  if(faudes_thread_tlsidx==TLS_OUT_OF_INDEXES)
324  return FAUDES_THREAD_ERROR;
325  // malloc my thread structure
326  *thr = (faudes_thread_t) malloc(sizeof(faudes_thread_record_t));
327  if(!*thr) return FAUDES_THREAD_ERROR;
328  // initialze my thread structure with function and argument
329  (*thr)->mFnct = fnct;
330  (*thr)->mArg = arg;
331  (*thr)->mRes = NULL;
332  // start the thread
333  (*thr)->mHandle = (HANDLE) _beginthreadex(NULL, 0, faudes_thread_wrapper, (void*) (*thr), 0, NULL);
334  // done
335  return (*thr)->mHandle ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
336 }
337 
338 // Thread functions (Windows to mimic pthreads)
339 faudes_thread_t faudes_thread_current(void) {
340  // retrieve my thread struct from tls
341  faudes_thread_t fthread = (faudes_thread_t) TlsGetValue(faudes_thread_tlsidx);
342  // note: returns NULL for parent thread
343  return fthread;
344 }
345 
346 // Thread functions (Windows to mimic pthreads)
347 int faudes_thread_detach(faudes_thread_t thr) {
348  CloseHandle(thr->mHandle);
349  // free my mem
350  free(thr);
351  return FAUDES_THREAD_SUCCESS;
352 }
353 
354 // Thread functions (Windows to mimic pthreads)
355 int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1) {
356  // the parent thread has no tls record and thus reports NULL
357  if( (thr0==NULL) && (thr1=NULL) ) return true;
358  if( (thr0==NULL) || (thr1=NULL) ) return false;
359  // std case, compare by handle
360  return thr0->mHandle == thr1->mHandle;
361 }
362 
363 // Thread functions (Windows to mimic pthreads)
364 void faudes_thread_exit(void *res) {
365  // retrieve thread structure from tls to pass on result
366  faudes_thread_t fthread = (faudes_thread_t) TlsGetValue(faudes_thread_tlsidx);
367  if(fthread) fthread->mRes=res;
368  // call winapi
369  ExitThread(0);
370 }
371 
372 // Thread functions (Windows to mimic pthreads)
373 int faudes_thread_join(faudes_thread_t thr, void **res) {
374  // default result
375  if(res) *res = 0;
376  // do the join
377  DWORD rc = WaitForSingleObject(thr->mHandle, INFINITE);
378  // retrieve result from thread structure
379  if( (rc!=WAIT_FAILED) && (res)) *res = thr->mRes;
380  // free mem
381  free(thr);
382  // done
383  if(rc == WAIT_FAILED) return FAUDES_THREAD_ERROR;
384  return FAUDES_THREAD_SUCCESS;
385 }
386 
387 #endif
388 #endif // Windows threads
389 
390 
391 
392 // straight PPOSIX mutexes (aka plain wrappers)
393 #ifdef FAUDES_THREADS
394 #ifdef FAUDES_POSIX
395 int faudes_mutex_init(faudes_mutex_t* mtx){
396  return pthread_mutex_init(mtx, NULL)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
397 }
398 void faudes_mutex_destroy(faudes_mutex_t* mtx){
399  pthread_mutex_destroy(mtx);
400 }
401 int faudes_mutex_lock(faudes_mutex_t *mtx) {
402  return pthread_mutex_lock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
403 }
404 int faudes_mutex_trylock(faudes_mutex_t *mtx){
405  return (pthread_mutex_trylock(mtx) == 0) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
406 }
407 int faudes_mutex_unlock(faudes_mutex_t *mtx){
408  return pthread_mutex_unlock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
409 }
410 #endif
411 #endif // POSIX mutexes
412 
413 // Windows to mimique PPOSIX mutexes
414 #ifdef FAUDES_THREADS
415 #ifdef FAUDES_WINDOWS
416 int faudes_mutex_init(faudes_mutex_t *mtx){
417  InitializeCriticalSection(mtx);
418  return FAUDES_THREAD_SUCCESS;
419 }
420 void faudes_mutex_destroy(faudes_mutex_t *mtx){
421  DeleteCriticalSection(mtx);
422 }
423 int faudes_mutex_lock(faudes_mutex_t *mtx) {
424  EnterCriticalSection(mtx);
425  return FAUDES_THREAD_SUCCESS;
426 }
427 int faudes_mutex_trylock(faudes_mutex_t *mtx){
428  return TryEnterCriticalSection(mtx) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
429 }
430 int faudes_mutex_unlock(faudes_mutex_t *mtx){
431  LeaveCriticalSection(mtx);
432  return FAUDES_THREAD_SUCCESS;
433 }
434 #endif
435 #endif // Windows mutexes
436 
437 
438 // straight PPOSIX conditions (aka plain wrappers)
439 #ifdef FAUDES_THREADS
440 #ifdef FAUDES_POSIX
441 int faudes_cond_init(faudes_cond_t* cond) {
442  return pthread_cond_init(cond, NULL) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
443 }
444 void faudes_cond_destroy(faudes_cond_t* cond) {
445  pthread_cond_destroy(cond);
446 }
447 int faudes_cond_signal(faudes_cond_t *cond){
448  return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
449 }
450 int faudes_cond_broadcast(faudes_cond_t *cond) {
451  return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
452 }
453 int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx) {
454  return pthread_cond_wait(cond, mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
455 }
456 int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime) {
457  int ret = pthread_cond_timedwait(cond, mtx, abstime);
458  if(ret == ETIMEDOUT) return FAUDES_THREAD_TIMEOUT;
459  return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
460 }
461 // Extension: timed wait with duration as opposed to absolute time
462 int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration) {
463  faudes_systime_t abstime;
464  faudes_msdelay(duration,&abstime);
465  return faudes_cond_timedwait(cond,mtx,&abstime);
466 }
467 #endif
468 #endif // POSIX condition
469 
470 
471 // Windows to mimique POSIX conditions
472 // The approach to condition variables on Windows is taken from
473 // "Strategies for Implementing POSIX Condition Variables on Win32"
474 // by Douglas C. Schmidt and Irfan Pyarali, Department of Computer
475 // Science, Washington University.
476 #ifdef FAUDES_THREADS
477 #ifdef FAUDES_WINDOWS
478 
479 // Convenience access my two condition events
480 #define EVENT_SIGNAL 0
481 #define EVENT_BROADCAST 1
482 
483 // Condition functions (Windows to mimic plain pthread)
484 int faudes_cond_init(faudes_cond_t* cond) {
485  // #waiters=0, with mutexed access
486  cond->mWaitersCount = 0;
487  InitializeCriticalSection(&cond->mWaitersCountMutex);
488  // auto-reset event to signal the condition
489  cond->mEvents[EVENT_SIGNAL]=CreateEvent(NULL, FALSE, FALSE, NULL);
490  // manual-reset event to broadcast the condition
491  cond->mEvents[EVENT_BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL);
492  // initialisation succeeded
493  if(cond->mEvents[EVENT_SIGNAL] != NULL)
494  if(cond->mEvents[EVENT_BROADCAST] != NULL)
495  return FAUDES_THREAD_SUCCESS;
496  // allow for destroy even on failed initialisation
497  if(cond->mEvents[EVENT_SIGNAL] != NULL)
498  CloseHandle(cond->mEvents[EVENT_SIGNAL]);
499  if(cond->mEvents[EVENT_BROADCAST] != NULL)
500  CloseHandle(cond->mEvents[EVENT_BROADCAST]);
501  cond->mEvents[EVENT_BROADCAST] = NULL;
502  cond->mEvents[EVENT_SIGNAL]=NULL;
503  return FAUDES_THREAD_ERROR;
504 }
505 
506 // Condition functions (Windows to mimic plain pthread)
507 void faudes_cond_destroy(faudes_cond_t* cond) {
508  if(cond->mEvents[EVENT_SIGNAL] != NULL)
509  CloseHandle(cond->mEvents[EVENT_SIGNAL]);
510  if(cond->mEvents[EVENT_BROADCAST] != NULL)
511  CloseHandle(cond->mEvents[EVENT_BROADCAST]);
512  DeleteCriticalSection(&cond->mWaitersCountMutex);
513 }
514 
515 // Condition functions (Windows to mimic plain pthread)
516 int faudes_cond_signal(faudes_cond_t *cond){
517  int waiters;
518  // any waiters ?
519  EnterCriticalSection(&cond->mWaitersCountMutex);
520  waiters = (cond->mWaitersCount > 0);
521  LeaveCriticalSection(&cond->mWaitersCountMutex);
522  // set event (one waiter will see the auto-reset event)
523  if(waiters){
524  if(SetEvent(cond->mEvents[EVENT_SIGNAL]) == 0)
525  return FAUDES_THREAD_ERROR;
526  }
527  return FAUDES_THREAD_SUCCESS;
528 }
529 
530 // Condition functions (Windows to mimic plain pthread)
531 int faudes_cond_broadcast(faudes_cond_t *cond) {
532  int waiters;
533  // any waiters ?
534  EnterCriticalSection(&cond->mWaitersCountMutex);
535  waiters = (cond->mWaitersCount > 0);
536  LeaveCriticalSection(&cond->mWaitersCountMutex);
537  // set event (all waiters will see, last waiter does the manual-reset)
538  if(waiters) {
539  if(SetEvent(cond->mEvents[EVENT_BROADCAST]) == 0)
540  return FAUDES_THREAD_ERROR;
541  }
542  return FAUDES_THREAD_SUCCESS;
543 }
544 
545 // Condition functions (Windows to mimic plain pthread)
546 int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration) {
547  // increment #waiters
548  EnterCriticalSection(&cond->mWaitersCountMutex);
549  ++ cond->mWaitersCount;
550  LeaveCriticalSection(&cond->mWaitersCountMutex);
551  // release mutex while waiting
552  LeaveCriticalSection(mtx);
553  // wait for either event to be set
554  int res = WaitForMultipleObjects(2, cond->mEvents, FALSE, (DWORD) duration);
555  // maintane my data ...
556  EnterCriticalSection(&cond->mWaitersCountMutex);
557  // ... a) decrement #waiters
558  -- cond->mWaitersCount;
559  // ... b) test if this was a broadcast and we were the last waiter ...
560  int last =
561  (res == (WAIT_OBJECT_0 + EVENT_BROADCAST)) &&
562  (cond->mWaitersCount == 0);
563  LeaveCriticalSection(&cond->mWaitersCountMutex);
564  // ... c) if so, do a manual-reset of the event
565  if(last) ResetEvent(cond->mEvents[EVENT_BROADCAST]);
566  // reaquire mutex
567  EnterCriticalSection(mtx);
568  // uniform return value
569  if(res == (int) WAIT_TIMEOUT)
570  return FAUDES_THREAD_TIMEOUT;
571  if(res == (int) WAIT_FAILED)
572  return FAUDES_THREAD_ERROR;
573  return FAUDES_THREAD_SUCCESS;
574 }
575 
576 // Condition functions (Windows to mimic plain pthread)
577 int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx) {
578  return faudes_cond_reltimedwait(cond, mtx, INFINITE);
579 }
580 
581 // Condition functions (Windows to mimic plain pthread)
582 int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime) {
583  // get absolute time
584  faudes_systime_t now;
585  faudes_gettimeofday(&now);
586  // convert to rel. time in secs
587  DWORD rels = abstime->tv_sec - now.tv_sec;
588  // saturation on overflow
589  if(rels > (4294967295u/1000)-1) rels = 4294967295u/1000-1;
590  // convert to rel. time in msecs
591  DWORD relms = rels*1000 + (abstime->tv_nsec - now.tv_nsec + 500000) / 1000000;
592  // pass on to reltimedwait
593  return faudes_cond_reltimedwait(cond, mtx, relms);
594 }
595 
596 #endif
597 #endif // Windows conditions
598 
599 
600 
601 
602 
603 
604 
Compiletime options.
faudes_systime_t gPerfTimer1
const std::string & faudes_pathseps(void)
void faudes_usdelay(faudes_mstime_t usecs, faudes_systime_t *end)
const char * faudes_strsignal(int sig)
void faudes_termsignal(void(*sighandler)(int))
void faudes_sumsystime(const faudes_systime_t &begin, const faudes_systime_t &duration, faudes_systime_t *res)
void faudes_sleep(long int sec)
const std::string & faudes_pathsep(void)
void faudes_invalid(const std::string &msg)
void faudes_usleep(long int usec)
void faudes_msdelay(faudes_mstime_t msecs, faudes_systime_t *end)
void faudes_diffsystime(const faudes_systime_t &end, const faudes_systime_t &begin, faudes_systime_t *res)
Platform dependant wrappers.

libFAUDES 2.32f --- 2024.12.22 --- c++ api documentaion by doxygen