libFAUDES
Sections
Index
|
cfl_platform.cppGo to the documentation of this file.00001 /** @file cfl_platform.cpp 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 00024 // My header 00025 #include "cfl_definitions.h" 00026 #include "cfl_platform.h" 00027 00028 // Extra header 00029 #include <signal.h> 00030 00031 00032 // Path separator (statics, see faudes_pathsep) 00033 #ifdef FAUDES_POSIX 00034 const std::string faudes_pathseps_str = "/"; 00035 const std::string faudes_pathsep_str = "/"; 00036 #endif 00037 #ifdef FAUDES_WINDOWS 00038 const std::string faudes_pathseps_str = "\\:/"; 00039 const std::string faudes_pathsep_str = "\\"; 00040 #endif 00041 00042 00043 // Uniform signalhandler on termination 00044 void faudes_termsignal(void (*sighandler)(int)) { 00045 #ifdef SIGTERM 00046 signal(SIGTERM, sighandler); 00047 #endif 00048 #ifdef SIGINT 00049 signal(SIGINT, sighandler); 00050 #endif 00051 #ifdef SIGQUIT 00052 signal(SIGQUIT, sighandler); 00053 #endif 00054 #ifdef SIGHUP 00055 signal(SIGHUP, sighandler); 00056 #endif 00057 #ifdef SIGABRT 00058 signal(SIGABRT, sighandler); 00059 #endif 00060 } 00061 00062 // Uniform signal names for POSIX / Windows/MinGW (see e.g. simfaudes.cpp) 00063 const char* faudes_strsignal(int sig) { 00064 #ifdef FAUDES_POSIX 00065 return strsignal(sig); 00066 #endif 00067 #ifdef FAUDES_WINDOWS 00068 return "unknown"; 00069 #endif 00070 } 00071 00072 00073 #ifdef FAUDES_SYSTIME 00074 00075 00076 // Uniform system time (using pthread timespec semantics, trust MinGW to provide) 00077 #if defined(FAUDES_POSIX) || defined(FAUDES_WINDOWS) 00078 void faudes_gettimeofday(faudes_systime_t* now) { 00079 timeval nowval; 00080 gettimeofday(&nowval,0); 00081 now->tv_sec=nowval.tv_sec; 00082 now->tv_nsec=nowval.tv_usec * 1000; 00083 } 00084 #endif 00085 00086 // Uniform system time (supporting functions) 00087 void faudes_diffsystime(const faudes_systime_t& end, const faudes_systime_t& begin, faudes_systime_t* res) { 00088 res->tv_sec = end.tv_sec-begin.tv_sec; 00089 res->tv_nsec = end.tv_nsec-begin.tv_nsec; 00090 if(res->tv_nsec <= 0){ 00091 res->tv_sec--; 00092 res->tv_nsec += 1000000000; 00093 } 00094 } 00095 00096 // Uniform system time (supporting functions) 00097 void faudes_sumsystime(const faudes_systime_t& begin, const faudes_systime_t& duration, faudes_systime_t* res) { 00098 res->tv_sec = begin.tv_sec + duration.tv_sec; 00099 res->tv_nsec = begin.tv_nsec + duration.tv_nsec; 00100 if(res->tv_nsec >= 1000000000) { 00101 res->tv_sec++; 00102 res->tv_nsec-=1000000000; 00103 } 00104 } 00105 00106 // Uniform system time (supporting functions) 00107 void faudes_msdelay(faudes_mstime_t msecs,faudes_systime_t* end) { 00108 faudes_systime_t now; 00109 faudes_gettimeofday(&now); 00110 faudes_systime_t delta; 00111 delta.tv_sec = msecs/1000; 00112 delta.tv_nsec = (msecs % 1000) *1000000; 00113 faudes_sumsystime(now,delta,end); 00114 } 00115 00116 // Uniform system time (supporting functions) 00117 void faudes_usdelay(faudes_mstime_t usecs,faudes_systime_t* end) { 00118 faudes_systime_t now; 00119 faudes_gettimeofday(&now); 00120 faudes_systime_t delta; 00121 delta.tv_sec = usecs/1000000; 00122 delta.tv_nsec = (usecs % 1000000) * 1000; 00123 faudes_sumsystime(now,delta,end); 00124 } 00125 00126 00127 #endif // systime 00128 00129 00130 #ifdef FAUDES_NETWORK 00131 00132 00133 // Uniform socketoption: test for error 00134 int faudes_getsocket_error(int fd) { 00135 #ifdef FAUDES_POSIX 00136 int opt=0; 00137 socklen_t len = sizeof(opt); 00138 int res = getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &len) < 0 ? -1 : 0; 00139 if(opt!=0) res=-1; 00140 return res; 00141 #endif 00142 #ifdef FAUDES_WINDOWS 00143 int opt=0; 00144 socklen_t len = sizeof(opt); 00145 int res = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 ? -1 : 0; 00146 if(opt!=0) res=-1; 00147 return res; 00148 #endif 00149 } 00150 00151 // Uniform socketoption: set nonblocking 00152 int faudes_setsocket_nonblocking(int fd, bool noblo) { 00153 #ifdef FAUDES_POSIX 00154 int sopt=fcntl(fd, F_GETFL, NULL); 00155 if(sopt<0) return -1; // error 00156 if(noblo) { 00157 int rc=fcntl(fd, F_SETFL, sopt|O_NONBLOCK); 00158 return rc < 0 ? -1 : 0; 00159 } else { 00160 int rc=fcntl(fd, F_SETFL, sopt& (~O_NONBLOCK)); 00161 return rc < 0 ? -1 : 0; 00162 } 00163 #endif 00164 #ifdef FAUDES_WINDOWS 00165 unsigned long onoff=0; 00166 if(noblo) onoff=1; 00167 return ioctlsocket(fd, FIONBIO, &onoff) == SOCKET_ERROR ? -1 : 0; 00168 #endif 00169 } 00170 00171 00172 00173 00174 00175 00176 #endif // network 00177 00178 00179 #ifdef FAUDES_THREADS 00180 00181 00182 // Use Windows thread local storage to implement pointer-typed return values 00183 #ifdef FAUDES_WINDOWS 00184 DWORD faudes_thread_tlsidx=TLS_OUT_OF_INDEXES; 00185 #endif 00186 00187 // Windows thread function wrapper with faudes_thread_t argument; 00188 #ifdef FAUDES_WINDOWS 00189 static unsigned WINAPI faudes_thread_wrapper(void *argfth) { 00190 // access my thread struct 00191 faudes_thread_t fthread = (faudes_thread_t) argfth; 00192 // record my thread struct as tls 00193 TlsSetValue(faudes_thread_tlsidx,fthread); 00194 // extract actual function an arguments 00195 void *(*fnct)(void*) = fthread->mFnct; 00196 void *arg = fthread->mArg; 00197 // call function 00198 void* res = fnct(arg); 00199 // uniform exit to retrieve return value 00200 faudes_thread_exit(res); 00201 // return dummy 00202 return 0; 00203 } 00204 #endif 00205 00206 // Thread functions (Windows to mimic pthreads) 00207 #ifdef FAUDES_WINDOWS 00208 int faudes_thread_create(faudes_thread_t *thr, void *(*fnct)(void *), void *arg){ 00209 // initialize thread local storage block 00210 if(faudes_thread_tlsidx==TLS_OUT_OF_INDEXES) 00211 faudes_thread_tlsidx=TlsAlloc(); 00212 if(faudes_thread_tlsidx==TLS_OUT_OF_INDEXES) 00213 return FAUDES_THREAD_ERROR; 00214 // malloc my thread structure 00215 *thr = (faudes_thread_t) malloc(sizeof(faudes_thread_record_t)); 00216 if(!*thr) return FAUDES_THREAD_ERROR; 00217 // initialze my thread structure with function and argument 00218 (*thr)->mFnct = fnct; 00219 (*thr)->mArg = arg; 00220 (*thr)->mRes = NULL; 00221 // start the thread 00222 (*thr)->mHandle = (HANDLE) _beginthreadex(NULL, 0, faudes_thread_wrapper, (void*) (*thr), 0, NULL); 00223 // done 00224 return (*thr)->mHandle ? FAUDES_THREAD_SUCCESS : FAUDES_THREAD_ERROR; 00225 } 00226 #endif 00227 00228 #ifdef FAUDES_WINDOWS 00229 // Thread functions (Windows to mimic pthreads) 00230 faudes_thread_t faudes_thread_current(void) { 00231 // retrieve my thread struct from tls 00232 faudes_thread_t fthread = (faudes_thread_t) TlsGetValue(faudes_thread_tlsidx); 00233 // note: returns NULL for parent thread 00234 return fthread; 00235 } 00236 #endif 00237 00238 #ifdef FAUDES_WINDOWS 00239 // Thread functions (Windows to mimic pthreads) 00240 int faudes_thread_detach(faudes_thread_t thr) { 00241 CloseHandle(thr->mHandle); 00242 // free my mem 00243 free(thr); 00244 return FAUDES_THREAD_SUCCESS; 00245 } 00246 #endif 00247 00248 #ifdef FAUDES_WINDOWS 00249 // Thread functions (Windows to mimic pthreads) 00250 int faudes_thread_equal(faudes_thread_t thr0, faudes_thread_t thr1) { 00251 // the parent thread has no tls record and thus reports NULL 00252 if( (thr0==NULL) && (thr1=NULL) ) return true; 00253 if( (thr0==NULL) || (thr1=NULL) ) return false; 00254 // std case, compare by handle 00255 return thr0->mHandle == thr1->mHandle; 00256 } 00257 #endif 00258 00259 #ifdef FAUDES_WINDOWS 00260 // Thread functions (Windows to mimic pthreads) 00261 void faudes_thread_exit(void *res) { 00262 // retrieve thread structure from tls to pass on result 00263 faudes_thread_t fthread = (faudes_thread_t) TlsGetValue(faudes_thread_tlsidx); 00264 if(fthread) fthread->mRes=res; 00265 // call winapi 00266 ExitThread(0); 00267 } 00268 #endif 00269 00270 #ifdef FAUDES_WINDOWS 00271 // Thread functions (Windows to mimic pthreads) 00272 int faudes_thread_join(faudes_thread_t thr, void **res) { 00273 // default result 00274 if(res) *res = 0; 00275 // do the join 00276 DWORD rc = WaitForSingleObject(thr->mHandle, INFINITE); 00277 // retrieve result from thread structure 00278 if( (rc!=WAIT_FAILED) && (res)) *res = thr->mRes; 00279 // free mem 00280 free(thr); 00281 // done 00282 if(rc == WAIT_FAILED) return FAUDES_THREAD_ERROR; 00283 return FAUDES_THREAD_SUCCESS; 00284 } 00285 #endif 00286 00287 // The approach to condition variables on Windows is taken from 00288 // "Strategies for Implementing POSIX Condition Variables on Win32" 00289 // by Douglas C. Schmidt and Irfan Pyarali, Department of Computer 00290 // Science, Washington University. 00291 00292 // Convenience access my two condition events 00293 #ifdef FAUDES_WINDOWS 00294 #define EVENT_SIGNAL 0 00295 #define EVENT_BROADCAST 1 00296 #endif 00297 00298 // Condition functions (Windows to mimic plain pthread) 00299 #ifdef FAUDES_WINDOWS 00300 int faudes_cond_init(faudes_cond_t* cond) { 00301 // #waiters=0, with mutexed access 00302 cond->mWaitersCount = 0; 00303 InitializeCriticalSection(&cond->mWaitersCountMutex); 00304 // auto-reset event to signal the condition 00305 cond->mEvents[EVENT_SIGNAL]=CreateEvent(NULL, FALSE, FALSE, NULL); 00306 // manual-reset event to broadcast the condition 00307 cond->mEvents[EVENT_BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL); 00308 // initialisation succeeded 00309 if(cond->mEvents[EVENT_SIGNAL] != NULL) 00310 if(cond->mEvents[EVENT_BROADCAST] != NULL) 00311 return FAUDES_THREAD_SUCCESS; 00312 // allow for destroy even on failed initialisation 00313 if(cond->mEvents[EVENT_SIGNAL] != NULL) 00314 CloseHandle(cond->mEvents[EVENT_SIGNAL]); 00315 if(cond->mEvents[EVENT_BROADCAST] != NULL) 00316 CloseHandle(cond->mEvents[EVENT_BROADCAST]); 00317 cond->mEvents[EVENT_BROADCAST] = NULL; 00318 cond->mEvents[EVENT_SIGNAL]=NULL; 00319 return FAUDES_THREAD_ERROR; 00320 } 00321 #endif 00322 00323 #ifdef FAUDES_WINDOWS 00324 // Condition functions (Windows to mimic plain pthread) 00325 void faudes_cond_destroy(faudes_cond_t* cond) { 00326 if(cond->mEvents[EVENT_SIGNAL] != NULL) 00327 CloseHandle(cond->mEvents[EVENT_SIGNAL]); 00328 if(cond->mEvents[EVENT_BROADCAST] != NULL) 00329 CloseHandle(cond->mEvents[EVENT_BROADCAST]); 00330 DeleteCriticalSection(&cond->mWaitersCountMutex); 00331 } 00332 #endif 00333 00334 #ifdef FAUDES_WINDOWS 00335 // Condition functions (Windows to mimic plain pthread) 00336 int faudes_cond_signal(faudes_cond_t *cond){ 00337 int waiters; 00338 // any waiters ? 00339 EnterCriticalSection(&cond->mWaitersCountMutex); 00340 waiters = (cond->mWaitersCount > 0); 00341 LeaveCriticalSection(&cond->mWaitersCountMutex); 00342 // set event (one waiter will see the auto-reset event) 00343 if(waiters){ 00344 if(SetEvent(cond->mEvents[EVENT_SIGNAL]) == 0) 00345 return FAUDES_THREAD_ERROR; 00346 } 00347 return FAUDES_THREAD_SUCCESS; 00348 } 00349 #endif 00350 00351 #ifdef FAUDES_WINDOWS 00352 // Condition functions (Windows to mimic plain pthread) 00353 int faudes_cond_broadcast(faudes_cond_t *cond) { 00354 int waiters; 00355 // any waiters ? 00356 EnterCriticalSection(&cond->mWaitersCountMutex); 00357 waiters = (cond->mWaitersCount > 0); 00358 LeaveCriticalSection(&cond->mWaitersCountMutex); 00359 // set event (all waiters will see, last waiter does the manual-reset) 00360 if(waiters) { 00361 if(SetEvent(cond->mEvents[EVENT_BROADCAST]) == 0) 00362 return FAUDES_THREAD_ERROR; 00363 } 00364 return FAUDES_THREAD_SUCCESS; 00365 } 00366 #endif 00367 00368 #ifdef FAUDES_WINDOWS 00369 // Condition functions (Windows to mimic plain pthread) 00370 int faudes_cond_reltimedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, faudes_mstime_t duration) { 00371 // increment #waiters 00372 EnterCriticalSection(&cond->mWaitersCountMutex); 00373 ++ cond->mWaitersCount; 00374 LeaveCriticalSection(&cond->mWaitersCountMutex); 00375 // release mutex while waiting 00376 LeaveCriticalSection(mtx); 00377 // wait for either event to be set 00378 int res = WaitForMultipleObjects(2, cond->mEvents, FALSE, (DWORD) duration); 00379 // maintane my data ... 00380 EnterCriticalSection(&cond->mWaitersCountMutex); 00381 // ... a) decrement #waiters 00382 -- cond->mWaitersCount; 00383 // ... b) test if this was a broadcast and we were the last waiter ... 00384 int last = 00385 (res == (WAIT_OBJECT_0 + EVENT_BROADCAST)) && 00386 (cond->mWaitersCount == 0); 00387 LeaveCriticalSection(&cond->mWaitersCountMutex); 00388 // ... c) if so, do a manual-reset of the event 00389 if(last) ResetEvent(cond->mEvents[EVENT_BROADCAST]); 00390 // reaquire mutex 00391 EnterCriticalSection(mtx); 00392 // uniform return value 00393 if(res == (int) WAIT_TIMEOUT) 00394 return FAUDES_THREAD_TIMEOUT; 00395 if(res == (int) WAIT_FAILED) 00396 return FAUDES_THREAD_ERROR; 00397 return FAUDES_THREAD_SUCCESS; 00398 } 00399 #endif 00400 00401 #ifdef FAUDES_WINDOWS 00402 // Condition functions (Windows to mimic plain pthread) 00403 int faudes_cond_wait(faudes_cond_t *cond, faudes_mutex_t *mtx) { 00404 return faudes_cond_reltimedwait(cond, mtx, INFINITE); 00405 } 00406 #endif 00407 00408 #ifdef FAUDES_WINDOWS 00409 // Condition functions (Windows to mimic plain pthread) 00410 int faudes_cond_timedwait(faudes_cond_t *cond, faudes_mutex_t *mtx, const faudes_systime_t *abstime) { 00411 // get absolute time 00412 faudes_systime_t now; 00413 faudes_gettimeofday(&now); 00414 // convert to rel. time in secs 00415 DWORD rels = abstime->tv_sec - now.tv_sec; 00416 // saturation on overflow 00417 if(rels > (4294967295u/1000)-1) rels = 4294967295u/1000-1; 00418 // convert to rel. time in msecs 00419 DWORD relms = rels*1000 + (abstime->tv_nsec - now.tv_nsec + 500000) / 1000000; 00420 // pass on to reltimedwait 00421 return faudes_cond_reltimedwait(cond, mtx, relms); 00422 } 00423 #endif 00424 00425 00426 #endif // threads 00427 00428 00429 00430 |
libFAUDES 2.22s --- 2013.10.07 --- c++ source docu by doxygen