cfl_platform.h
Go to the documentation of this file.
1 /** @file cfl_platform.h Platform dependant wrappers */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2013 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 #ifndef FAUDES_PLATFORM_H
24 #define FAUDES_PLATFORM_H
25 
26 /** Sense POSIX versus Windows */
27 #ifndef FAUDES_POSIX
28 #ifndef FAUDES_WINDOWS
29 #ifndef FAUDES_GENERIC
30 
31 #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
32 #define FAUDES_WINDOWS
33 #endif
34 #if defined (__unix__) || (__linus__) || (__linux__) || (defined (__APPLE__) && defined (__MACH__))
35 #define FAUDES_POSIX
36 #endif
37 
38 #ifndef FAUDES_POSIX
39 #ifndef FAUDES_WINDOWS
40 #define FAUDES_GENERIC
41 #endif
42 #endif
43 
44 #endif
45 #endif
46 #endif
47 
48 
49 /** Interface export/import symbols: windows */
50 #ifdef FAUDES_WINDOWS
51 #ifdef FAUDES_BUILD_DSO
52  #ifdef __GNUC__
53  #define FAUDES_API __attribute__ ((dllexport))
54  #else
55  #define FAUDES_API __declspec(dllexport)
56  #endif
57 #endif
58 #ifdef FAUDES_BUILD_APP
59  #ifdef __GNUC__
60  #define FAUDES_API __attribute__ ((dllimport))
61  #else
62  #define FAUDES_API __declspec(dllimport)
63  #endif
64 #endif
65 #endif
66 
67 /** Interface export/import symbols: posix/gcc */
68 #ifdef FAUDES_POSIX
69 #ifdef FAUDES_BUILD_DSO
70  #if __GNUC__ >= 4
71  #define FAUDES_API __attribute__ ((visibility ("default")))
72  #endif
73 #endif
74 #ifdef FAUDES_BUILD_APP
75  #define FAUDES_API
76 #endif
77 #endif
78 
79 /** Interface export/import symbols: default */
80 #ifndef FAUDES_API
81  #define FAUDES_API
82 #endif
83 
84 
85 
86 // Std headers
87 #include <cstdlib>
88 #include <cstring>
89 #include <inttypes.h>
90 #include <limits>
91 #include <string>
92 #include <iostream>
93 #include <sstream>
94 #include <fstream>
95 #include <iomanip>
96 #include <map>
97 #include <set>
98 #include <vector>
99 #include <stack>
100 #include <iterator>
101 
102 
103 // Extra POSIX headers
104 #ifdef FAUDES_POSIX
105 
106 #include <stdlib.h>
107 #include <cerrno>
108 #include <fcntl.h>
109 #include <unistd.h>
110 #include <dirent.h>
111 
112 #ifdef FAUDES_SYSTIME
113 #include <time.h>
114 #include <sys/time.h>
115 #endif
116 
117 #ifdef FAUDES_NETWORK
118 #include <sys/socket.h>
119 #include <arpa/inet.h>
120 #include <netdb.h>
121 #endif
122 
123 #ifdef FAUDES_THREADS
124 #include <pthread.h>
125 #endif
126 
127 #endif
128 
129 
130 // Extra Windows headers
131 #ifdef FAUDES_WINDOWS
132 
133 #ifndef WIN32_LEAN_AND_MEAN
134 #define WIN32_LEAN_AND_MEAN
135 #define FAUDES_LEAN_AND_MEAN
136 #endif
137 #include <windows.h>
138 #ifdef FAUDES_LEAN_AND_MEAN
139 #undef FAUDES_LEAN_AND_MEAN
140 #undef WIN32_LEAN_AND_MEAN
141 #endif
142 
143 #ifdef FAUDES_SYSTIME
144 #include <time.h> // ok for cl
145 //#include <sys/time.h> //mingw only
146 #include <mmsystem.h>
147 #endif
148 
149 #ifdef FAUDES_NETWORK
150 #include <winsock2.h>
151 #include <fcntl.h>
152 #endif
153 
154 #ifdef FAUDES_THREADS
155 #include <process.h>
156 #endif
157 
158 #include <io.h>
159 
160 // dislike min/max msvc macros
161 #ifdef max
162 #undef max
163 #endif
164 #ifdef min
165 #undef min
166 #endif
167 
168 #endif
169 
170 
171 
172 // Path-seperators (see cfl_helper.cpp)
173 // * the first separator is the one used to prepend directories etc
174 // * all other separators are used to extract basenames
175 // * using gcc/make also on Windows, we occasionaly get Unix style files names
176 // in the build process ... thus we allways define the Unix "/" as a separator
177 // * summary: we use "/" for POSIX and "\\:/" for Windows.
178 extern FAUDES_API const std::string faudes_pathseps_str;
179 inline FAUDES_API const std::string& faudes_pathseps(void) {
180  return faudes_pathseps_str;
181 }
182 
183 // Path-seperator (first char of above, see cfl_helper.cpp)
184 extern FAUDES_API const std::string faudes_pathsep_str;
185 inline FAUDES_API const std::string& faudes_pathsep(void) {
186  return faudes_pathsep_str;
187 }
188 
189 
190 // Uniform exit-signalhandler for POSIX/Windows (see e.g. simfaudes.cpp)
191 extern FAUDES_API void faudes_termsignal(void (*sighandler)(int));
192 
193 // Uniform signal names for POSIX/Windows (see e.g. simfaudes.cpp)
194 extern FAUDES_API const char* faudes_strsignal(int sig);
195 
196 // Uniform sleep for POSIX/Windows (see e.g. iodevice plug-in)
197 #ifdef FAUDES_POSIX
198 inline FAUDES_API void faudes_sleep(long int sec) {sleep(sec);}
199 inline FAUDES_API void faudes_usleep(long int usec) {usleep(usec);}
200 #endif
201 #ifdef FAUDES_WINDOWS
202 inline FAUDES_API void faudes_sleep(long int sec) {Sleep((sec) * 1000);}
203 inline FAUDES_API void faudes_usleep(long int usec) {Sleep((usec) / 1000);}
204 #endif
205 #ifdef FAUDES_GENERIC
206 extern FAUDES_API void faudes_invalid(const std::string& msg);
207 inline FAUDES_API void faudes_sleep(long int sec) { faudes_invalid("faudes_sleep()"); }
208 inline FAUDES_API void faudes_usleep(long int usec) { faudes_invalid("faudes_usleep()"); }
209 #endif
210 
211 
212 #ifdef FAUDES_SYSTIME
213 
214 // Uniform system time using POSIX pthreads semantics
215 #ifdef FAUDES_POSIX
216 typedef timespec faudes_systime_t;
217 typedef long int faudes_mstime_t;
218 #endif
219 #ifdef FAUDES_WINDOWS
220 typedef struct {
221  long int tv_sec;
222  long int tv_nsec;
223 } faudes_systime_t;
224 typedef long int faudes_mstime_t;
225 #endif
226 #ifdef FAUDES_GENERIC
227 #error option systime not available on generic platform
228 #endif
229 
230 
231 // Uniform system time definitions
232 extern FAUDES_API void faudes_gettimeofday(faudes_systime_t* now);
233 extern FAUDES_API void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_systime_t* res);
234 extern FAUDES_API void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_mstime_t* res);
235 extern FAUDES_API void faudes_sumsystime(const faudes_systime_t& begin, const faudes_systime_t& duration, faudes_systime_t* res);
236 extern FAUDES_API void faudes_msdelay(faudes_mstime_t msecs,faudes_systime_t* end);
237 extern FAUDES_API void faudes_usdelay(faudes_mstime_t usecs,faudes_systime_t* end);
238 
239 // global performance times
240 extern FAUDES_API faudes_systime_t gPerfTimer1;
241 
242 #endif
243 
244 
245 
246 #ifdef FAUDES_NETWORK
247 
248 // Uniform POSIX sockets (see iop_modbus.cpp and iop_simplenet.cpp)
249 #ifdef FAUDES_POSIX
250 inline FAUDES_API int faudes_closesocket(int fd) {return close(fd);}
251 inline FAUDES_API int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
252  return setsockopt(fd,level,optname,optval,optlen);}
253 inline FAUDES_API int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
254  return getsockopt(fd,level,optname,optval,optlen);}
255 extern FAUDES_API int faudes_setsocket_nonblocking(int fd, bool noblo);
256 extern FAUDES_API int faudes_getsocket_error(int fd);
257 #endif
258 #ifdef FAUDES_WINDOWS
259 typedef int socklen_t;
260 inline FAUDES_API int faudes_closesocket(int fd) {return closesocket(fd);}
261 inline FAUDES_API int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
262  return setsockopt(fd,level,optname,(char*) optval,optlen);}
263 inline FAUDES_API int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
264  return getsockopt(fd,level,optname,(char*) optval,optlen);}
265 extern FAUDES_API int faudes_setsocket_nonblocking(int fd, bool noblo);
266 extern FAUDES_API int faudes_getsocket_error(int fd);
267 #endif
268 #ifdef FAUDES_GENERIC
269 #error option network not available on generic platform
270 #endif
271 
272 // POSIX sockets to have BSD style REUSEPORT option (see iop_modbus.cpp and iop_simplenet.cpp)
273 #ifndef SO_REUSEPORT
274 #define SO_REUSEPORT SO_REUSEADDR
275 #endif
276 
277 #endif
278 
279 
280 #ifdef FAUDES_THREADS
281 
282 /*
283 The remaining section of this file provides elementary support for threads,
284 using a minimalistic subset of the POSIX threads interface. It is tailored for
285 the use of edge-detection and networking as required by the iodevice plug-in.
286 In general, libFAUDES is not threadsafe due to global variables, e.g.
287 symoltables. This may change in a future revision.
288 */
289 
290 
291 // Common return codes
292 #define FAUDES_THREAD_SUCCESS 0
293 #define FAUDES_THREAD_ERROR 1
294 #define FAUDES_THREAD_TIMEOUT 2
295 
296 
297 
298 #ifdef FAUDES_POSIX
299 // Thread data type (use plain POSIX thread)
300 typedef pthread_t faudes_thread_t;
301 // Thread functions (all inline, plain pthread wrapper)
302 inline FAUDES_API int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg){
303  // prepare attribute for plain joinable thread
304  pthread_attr_t attr;
305  pthread_attr_init(&attr);
306  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
307  // start execute
308  int ret = pthread_create(thr, &attr, fnct, arg);
309  // done
310  pthread_attr_destroy(&attr);
311  return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
312 }
313 inline FAUDES_API faudes_thread_t faudes_thread_current(void) {
314  return pthread_self();
315 }
316 inline FAUDES_API int faudes_thread_detach(faudes_thread_t thr) {
317  return pthread_detach(thr)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
318 }
319 inline FAUDES_API int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1) {
320  return pthread_equal(thr0, thr1);
321 }
322 inline FAUDES_API void faudes_thread_exit(void* res) {
323  pthread_exit(res);
324 }
325 inline int faudes_thread_join(faudes_thread_t thr, void **res) {
326  return pthread_join(thr, res) == 0 ? FAUDES_THREAD_ERROR : FAUDES_THREAD_SUCCESS;
327 }
328 #endif
329 
330 
331 #ifdef FAUDES_WINDOWS
332 // Thread data type
333 // We wrap the client function to provide pointer-typed
334 // return values (as opposed to Windows int-typed return values)
335 typedef struct {
336  HANDLE mHandle; // Windows thread handle
337  void *(*mFnct)(void *); // client function
338  void *mArg; // argument
339  void *mRes; // result
340 } faudes_thread_record_t;
341 typedef faudes_thread_record_t* faudes_thread_t;
342 // Thread functions (Windows to mimic plain pthreads)
343 extern FAUDES_API int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg);
344 extern FAUDES_API faudes_thread_t faudes_thread_current(void);
345 extern FAUDES_API int faudes_thread_detach(faudes_thread_t thr);
346 extern FAUDES_API int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1);
347 extern FAUDES_API void faudes_thread_exit(void* res);
348 extern FAUDES_API int faudes_thread_join(faudes_thread_t thr, void **res);
349 #endif
350 
351 
352 #ifdef FAUDES_POSIX
353 // Mutex data type (use plain POSIX mutex)
354 typedef pthread_mutex_t faudes_mutex_t;
355 // Mutex functions (all inline, plain pthread wrapper)
356 inline FAUDES_API int faudes_mutex_init(faudes_mutex_t* mtx){
357  return pthread_mutex_init(mtx, NULL)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
358 }
359 inline FAUDES_API void faudes_mutex_destroy(faudes_mutex_t* mtx){
360  pthread_mutex_destroy(mtx);
361 }
362 inline FAUDES_API int faudes_mutex_lock(faudes_mutex_t *mtx) {
363  return pthread_mutex_lock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
364 }
365 inline FAUDES_API int faudes_mutex_trylock(faudes_mutex_t *mtx){
366  return (pthread_mutex_trylock(mtx) == 0) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
367 }
368 inline FAUDES_API int faudes_mutex_unlock(faudes_mutex_t *mtx){
369  return pthread_mutex_unlock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
370 }
371 #endif
372 
373 
374 #ifdef FAUDES_WINDOWS
375 // Mutex data type (use Windows "critical section")
376 typedef CRITICAL_SECTION faudes_mutex_t;
377 // Mutex functions (all inline, wraps to Windows "critical section")
378 inline FAUDES_API int faudes_mutex_init(faudes_mutex_t *mtx){
379  InitializeCriticalSection(mtx);
380  return FAUDES_THREAD_SUCCESS;
381 }
382 inline FAUDES_API void faudes_mutex_destroy(faudes_mutex_t *mtx){
383  DeleteCriticalSection(mtx);
384 }
385 inline FAUDES_API int faudes_mutex_lock(faudes_mutex_t *mtx) {
386  EnterCriticalSection(mtx);
387  return FAUDES_THREAD_SUCCESS;
388 }
389 inline FAUDES_API int faudes_mutex_trylock(faudes_mutex_t *mtx){
390  return TryEnterCriticalSection(mtx) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
391 }
392 inline FAUDES_API int faudes_mutex_unlock(faudes_mutex_t *mtx){
393  LeaveCriticalSection(mtx);
394  return FAUDES_THREAD_SUCCESS;
395 }
396 #endif
397 
398 
399 #ifdef FAUDES_POSIX
400 // Condition variable data type (use plain POSIX condition variables)
401 typedef pthread_cond_t faudes_cond_t;
402 // Condition functions (all inline, plain pthread wrapper)
403 inline FAUDES_API int faudes_cond_init(faudes_cond_t* cond) {
404  return pthread_cond_init(cond, NULL) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
405 }
406 inline FAUDES_API void faudes_cond_destroy(faudes_cond_t* cond) {
407  pthread_cond_destroy(cond);
408 }
409 inline FAUDES_API int faudes_cond_signal(faudes_cond_t *cond){
410  return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
411 }
412 inline FAUDES_API int faudes_cond_broadcast(faudes_cond_t *cond) {
413  return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
414 }
415 inline FAUDES_API int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx) {
416  return pthread_cond_wait(cond, mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
417 }
418 inline FAUDES_API int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime) {
419  int ret = pthread_cond_timedwait(cond, mtx, abstime);
420  if(ret == ETIMEDOUT) return FAUDES_THREAD_TIMEOUT;
421  return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
422 }
423 // Extension: timed wait with duration as opposed to absolute time
424 inline FAUDES_API int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration) {
425  faudes_systime_t abstime;
426  faudes_msdelay(duration,&abstime);
427  return faudes_cond_timedwait(cond,mtx,&abstime);
428 }
429 #endif
430 
431 
432 #ifdef FAUDES_WINDOWS
433 // Condition variable data type
434 // The approach is taken from "Strategies for Implementing POSIX Condition Variables
435 // on Win32" by Douglas C. Schmidt and Irfan Pyarali, Department of Computer
436 // Science, Washington University.
437 typedef struct {
438  HANDLE mEvents[2]; // signal and broadcast event handles
439  unsigned int mWaitersCount; // count the number of waiters
440  CRITICAL_SECTION mWaitersCountMutex; // mutex access to waiterscount
441 } faudes_cond_t;
442 // Condition functions (Windows to mimic plain pthread conditions)
443 extern FAUDES_API int faudes_cond_init(faudes_cond_t* cond);
444 extern FAUDES_API void faudes_cond_destroy(faudes_cond_t* cond);
445 extern FAUDES_API int faudes_cond_signal(faudes_cond_t *cond);
446 extern FAUDES_API int faudes_cond_broadcast(faudes_cond_t *cond);
447 extern FAUDES_API int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx);
448 extern FAUDES_API int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime);
449 extern FAUDES_API int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration);
450 #endif
451 
452 
453 
454 #ifdef FAUDES_GENERIC
455 #error option threads not available on generic platform
456 #endif
457 
458 
459 #endif // threads
460 
461 #endif // header
462 
faudes_systime_t gPerfTimer1
void faudes_usdelay(faudes_mstime_t usecs, faudes_systime_t *end)
int faudes_setsocket_nonblocking(int fd, bool noblo)
int faudes_getsocket_error(int fd)
void faudes_sumsystime(const faudes_systime_t &begin, const faudes_systime_t &duration, faudes_systime_t *res)
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)
#define FAUDES_API
Interface export/import symbols: windows.
Definition: cfl_platform.h:81
FAUDES_API void faudes_invalid(const std::string &msg)
FAUDES_API const std::string faudes_pathseps_str
FAUDES_API const std::string & faudes_pathsep(void)
Definition: cfl_platform.h:185
FAUDES_API void faudes_termsignal(void(*sighandler)(int))
FAUDES_API const std::string faudes_pathsep_str
FAUDES_API const char * faudes_strsignal(int sig)
FAUDES_API void faudes_usleep(long int usec)
Definition: cfl_platform.h:208
FAUDES_API void faudes_sleep(long int sec)
Definition: cfl_platform.h:207
FAUDES_API const std::string & faudes_pathseps(void)
Definition: cfl_platform.h:179

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen