cfl_platform.h

Go to the documentation of this file.
00001 /** @file cfl_platform.h  Platform dependant wrappers */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2013  Thomas Moor
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with this library; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00020 */
00021 
00022 
00023 #ifndef FAUDES_PLATFORM_H
00024 #define FAUDES_PLATFORM_H
00025 
00026 /** Sense POSIX versus Windows */
00027 #ifndef FAUDES_POSIX
00028 #ifndef FAUDES_WINDOWS
00029 
00030 #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
00031 #define FAUDES_WINDOWS
00032 #else
00033 #define FAUDES_POSIX
00034 #endif
00035 
00036 #endif
00037 #endif
00038 
00039 
00040 // Std headers 
00041 #include <cstdlib>
00042 #include <cstring>
00043 #include <limits>
00044 #include <string>
00045 #include <iostream>
00046 #include <sstream>
00047 #include <fstream>
00048 #include <iomanip>
00049 #include <map>
00050 #include <set>
00051 
00052 // Extra POSIX headers 
00053 #ifdef FAUDES_POSIX
00054 
00055 #include <stdlib.h>
00056 #include <cerrno>
00057 #include <fcntl.h>
00058 #include <unistd.h>
00059 
00060 #ifdef FAUDES_SYSTIME
00061 #include <time.h>
00062 #include <sys/time.h>
00063 #endif
00064 
00065 #ifdef FAUDES_NETWORK
00066 #include <sys/socket.h>
00067 #include <arpa/inet.h>
00068 #include <netdb.h>
00069 #endif
00070 
00071 #ifdef FAUDES_THREADS
00072 #include <pthread.h>
00073 #endif
00074 
00075 
00076 #endif
00077 
00078 
00079 // Extra Windows/MinGW headers
00080 #ifdef FAUDES_WINDOWS
00081 
00082 #ifndef WIN32_LEAN_AND_MEAN
00083 #define WIN32_LEAN_AND_MEAN
00084 #define FAUDES_LEAN_AND_MEAN
00085 #endif
00086 #include <windows.h>
00087 #ifdef FAUDES_LEAN_AND_MEAN
00088 #undef FAUDES_LEAN_AND_MEAN
00089 #undef WIN32_LEAN_AND_MEAN
00090 #endif
00091 
00092 #ifdef FAUDES_SYSTIME
00093 #include <time.h>
00094 #include <sys/time.h>
00095 #endif
00096 
00097 #ifdef FAUDES_NETWORK
00098 #include <winsock2.h>
00099 #include <fcntl.h>
00100 #endif
00101 
00102 #ifdef FAUDES_THREADS
00103 #include <process.h>
00104 #endif
00105 
00106 
00107 #endif
00108 
00109 
00110 
00111 // Path-seperators (see cfl_helper.cpp)
00112 //  * the first separator is the one used to prepend directories etc
00113 //  * all other separators are used to extract basenames
00114 //  * using gcc/make also on Windows, we occasionaly get Unix style files names
00115 //    in the build process ... thus we allways define the Unix "/" as a separator 
00116 //  * summary: we use "/" for POSIX and "\\:/" for Windows.
00117 extern const std::string faudes_pathseps_str; 
00118 inline const std::string& faudes_pathseps(void) { 
00119   return faudes_pathseps_str; 
00120 }
00121 
00122 // Path-seperator (first char of above, see cfl_helper.cpp)
00123 extern const std::string faudes_pathsep_str; 
00124 inline const std::string& faudes_pathsep(void) {
00125   return faudes_pathsep_str; 
00126 }
00127 
00128 
00129 // Uniform exit-signalhandler for POSIX / Windows/MinGW (see e.g. simfaudes.cpp)
00130 void faudes_termsignal(void (*sighandler)(int));
00131 
00132 // Uniform signal names for POSIX / Windows/MinGW (see e.g. simfaudes.cpp)
00133 const char* faudes_strsignal(int sig);
00134 
00135 // Uniform sleep for POSIX and Windows/MinGW (see e.g. iodevice plug-in)
00136 #ifdef FAUDES_POSIX
00137 inline void faudes_sleep(long int sec) {sleep(sec);}
00138 inline void faudes_usleep(long int usec) {usleep(usec);}
00139 #endif
00140 #ifdef FAUDES_WINDOWS
00141 inline void faudes_sleep(long int sec) {Sleep((sec) * 1000);}
00142 inline void faudes_usleep(long int usec) {Sleep((usec) / 1000);}
00143 #endif
00144 
00145 
00146 
00147 #ifdef FAUDES_SYSTIME
00148 
00149 // Uniform system time using POSIX pthreads semantics
00150 #ifdef FAUDES_POSIX
00151 typedef timespec faudes_systime_t;
00152 typedef long int faudes_mstime_t;
00153 #endif
00154 #ifdef FAUDES_WINDOWS
00155 typedef struct {
00156   long int tv_sec;
00157   long int tv_nsec;
00158 } faudes_systime_t;
00159 typedef long int faudes_mstime_t;
00160 #endif
00161 
00162 // Uniform system time definitions
00163 void faudes_gettimeofday(faudes_systime_t* now);
00164 void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_systime_t* res);
00165 void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_mstime_t* res);
00166 void faudes_sumsystime(const faudes_systime_t& begin, const faudes_systime_t& duration, faudes_systime_t* res);
00167 void faudes_msdelay(faudes_mstime_t msecs,faudes_systime_t* end);
00168 void faudes_usdelay(faudes_mstime_t usecs,faudes_systime_t* end);
00169 
00170 // global performance times
00171 extern faudes_systime_t gPerfTimer1;
00172 
00173 #endif
00174 
00175 
00176 
00177 #ifdef FAUDES_NETWORK
00178 
00179 // Uniform POSIX sockets (see iop_modbus.cpp and iop_simplenet.cpp)
00180 #ifdef FAUDES_POSIX
00181 inline  int faudes_closesocket(int fd) {return close(fd);}
00182 inline  int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
00183   return setsockopt(fd,level,optname,optval,optlen);}
00184 inline  int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
00185   return getsockopt(fd,level,optname,optval,optlen);}
00186 int faudes_setsocket_nonblocking(int fd, bool noblo);
00187 int faudes_getsocket_error(int fd);
00188 #endif
00189 #ifdef FAUDES_WINDOWS
00190 typedef int socklen_t;
00191 inline  int faudes_closesocket(int fd) {return closesocket(fd);}
00192 inline  int faudes_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) {
00193   return setsockopt(fd,level,optname,(char*) optval,optlen);}
00194 inline  int faudes_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) {
00195   return getsockopt(fd,level,optname,(char*) optval,optlen);}
00196 int faudes_setsocket_nonblocking(int fd, bool noblo);
00197 int faudes_getsocket_error(int fd);
00198 #endif
00199 
00200 // POSIX sockets to have BSD style REUSEPORT option (see iop_modbus.cpp and iop_simplenet.cpp)
00201 #ifndef SO_REUSEPORT
00202 #define SO_REUSEPORT SO_REUSEADDR
00203 #endif
00204 
00205 #endif
00206 
00207 
00208 #ifdef FAUDES_THREADS
00209 
00210 /* 
00211 The remaining section of this file provides elementary support for threads, 
00212 using a minimalistic subset of the POSIX threads interface. It is tailored for 
00213 the use of edge-detection and networking as required by the iodevice plug-in. 
00214 In general, libFAUDES is not threadsafe due to global variables, e.g. 
00215 symoltables. This may change in a future revision.
00216 */
00217 
00218 
00219 // Common return codes 
00220 #define FAUDES_THREAD_SUCCESS  0 
00221 #define FAUDES_THREAD_ERROR    1 
00222 #define FAUDES_THREAD_TIMEOUT  2 
00223 
00224 
00225 
00226 #ifdef FAUDES_POSIX
00227 // Thread data type (use plain POSIX thread)
00228 typedef pthread_t faudes_thread_t;
00229 // Thread functions (all inline, plain pthread wrapper)
00230 inline int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg){
00231   // prepare attribute for plain joinable thread
00232   pthread_attr_t attr;  
00233   pthread_attr_init(&attr);
00234   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00235   // start execute
00236   int ret  = pthread_create(thr, &attr, fnct, arg);
00237   // done
00238   pthread_attr_destroy(&attr);
00239   return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00240 }
00241 inline faudes_thread_t faudes_thread_current(void) {
00242   return pthread_self();
00243 }
00244 inline int faudes_thread_detach(faudes_thread_t thr) {
00245   return pthread_detach(thr)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00246 }
00247 inline int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1) {
00248   return pthread_equal(thr0, thr1);
00249 }
00250 inline void faudes_thread_exit(void* res) {
00251   pthread_exit(res);
00252 }
00253 inline int faudes_thread_join(faudes_thread_t thr, void **res) {
00254   return pthread_join(thr, res) == 0 ? FAUDES_THREAD_ERROR : FAUDES_THREAD_SUCCESS;
00255 }
00256 #endif
00257 
00258 
00259 #ifdef FAUDES_WINDOWS
00260 // Thread data type 
00261 // We wrap the client function to provide pointer-typed  
00262 // return values (as opposed to Windows int-typed return values)
00263 typedef struct {
00264   HANDLE mHandle;          // Windows thread handle             
00265   void *(*mFnct)(void *);  // client function
00266   void *mArg;              // argument
00267   void *mRes;              // result
00268 } faudes_thread_record_t;
00269 typedef faudes_thread_record_t* faudes_thread_t;
00270 // Thread functions (Windows to mimic plain pthreads)
00271 int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg);
00272 faudes_thread_t faudes_thread_current(void);
00273 int faudes_thread_detach(faudes_thread_t thr);
00274 int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1);
00275 void faudes_thread_exit(void* res);
00276 int faudes_thread_join(faudes_thread_t thr, void **res);
00277 #endif
00278 
00279 
00280 #ifdef FAUDES_POSIX
00281 // Mutex data type (use plain POSIX mutex)
00282 typedef pthread_mutex_t faudes_mutex_t;
00283 // Mutex functions (all inline, plain pthread wrapper)
00284 inline int faudes_mutex_init(faudes_mutex_t* mtx){
00285   return pthread_mutex_init(mtx, NULL)==0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00286 }
00287 inline void faudes_mutex_destroy(faudes_mutex_t* mtx){
00288   pthread_mutex_destroy(mtx);
00289 }
00290 inline int faudes_mutex_lock(faudes_mutex_t *mtx) {
00291   return pthread_mutex_lock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00292 }
00293 inline int faudes_mutex_trylock(faudes_mutex_t *mtx){
00294   return (pthread_mutex_trylock(mtx) == 0) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00295 }
00296 inline int faudes_mutex_unlock(faudes_mutex_t *mtx){
00297   return pthread_mutex_unlock(mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00298 }
00299 #endif
00300 
00301 
00302 #ifdef FAUDES_WINDOWS
00303 // Mutex data type (use Windows "critical section")
00304 typedef CRITICAL_SECTION faudes_mutex_t;
00305 // Mutex functions (all inline, wraps to Windows "critical section")
00306 inline int faudes_mutex_init(faudes_mutex_t *mtx){
00307   InitializeCriticalSection(mtx);
00308   return FAUDES_THREAD_SUCCESS;
00309 }
00310 inline void faudes_mutex_destroy(faudes_mutex_t *mtx){
00311   DeleteCriticalSection(mtx);
00312 }
00313 inline int faudes_mutex_lock(faudes_mutex_t *mtx) {
00314   EnterCriticalSection(mtx);
00315   return FAUDES_THREAD_SUCCESS;
00316 }
00317 inline int faudes_mutex_trylock(faudes_mutex_t *mtx){
00318   return TryEnterCriticalSection(mtx) ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00319 }
00320 inline int faudes_mutex_unlock(faudes_mutex_t *mtx){
00321   LeaveCriticalSection(mtx);
00322   return FAUDES_THREAD_SUCCESS;
00323 }
00324 #endif
00325 
00326 
00327 #ifdef FAUDES_POSIX
00328 // Condition variable data type (use plain POSIX condition variables)
00329 typedef pthread_cond_t faudes_cond_t;
00330 // Condition functions (all inline, plain pthread wrapper)
00331 inline int faudes_cond_init(faudes_cond_t* cond) {
00332   return pthread_cond_init(cond, NULL) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00333 }
00334 inline void faudes_cond_destroy(faudes_cond_t* cond) {
00335   pthread_cond_destroy(cond);
00336 }
00337 inline int faudes_cond_signal(faudes_cond_t *cond){
00338   return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00339 }
00340 inline int faudes_cond_broadcast(faudes_cond_t *cond) {
00341   return pthread_cond_signal(cond) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00342 }
00343 inline int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx) {
00344   return pthread_cond_wait(cond, mtx) == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00345 }
00346 inline int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime) {
00347   int ret = pthread_cond_timedwait(cond, mtx, abstime);
00348   if(ret == ETIMEDOUT) return FAUDES_THREAD_TIMEOUT;
00349   return ret == 0 ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR;
00350 }
00351 // Extension: timed wait with duration as opposed to absolute time
00352 inline int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration) {
00353   faudes_systime_t abstime;
00354   faudes_msdelay(duration,&abstime);
00355   return faudes_cond_timedwait(cond,mtx,&abstime);
00356 }
00357 #endif
00358 
00359 
00360 #ifdef FAUDES_WINDOWS
00361 // Condition variable data type 
00362 // The approach is taken from "Strategies for Implementing POSIX Condition Variables 
00363 // on Win32" by Douglas C. Schmidt and Irfan Pyarali, Department of Computer 
00364 // Science, Washington University. 
00365 typedef struct {
00366   HANDLE mEvents[2];                   // signal and broadcast event handles
00367   unsigned int mWaitersCount;          // count the number of waiters
00368   CRITICAL_SECTION mWaitersCountMutex; // mutex access to waiterscount
00369 } faudes_cond_t;
00370 // Condition functions (Windows to mimic plain pthread conditions)
00371 int faudes_cond_init(faudes_cond_t* cond);
00372 void faudes_cond_destroy(faudes_cond_t* cond);
00373 int faudes_cond_signal(faudes_cond_t *cond);
00374 int faudes_cond_broadcast(faudes_cond_t *cond);
00375 int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx);
00376 int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime);
00377 int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration);
00378 #endif
00379 
00380 
00381 
00382 
00383 
00384 #endif // threads
00385 
00386 #endif // header
00387 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen