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

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen