cfl_platform.hGo 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 |