cthread.c
Go to the documentation of this file.
00001 #include <assert.h>
00002 #include "stdafx.h"
00003 #include "cphidget.h"
00004 #include "cphidgetmanager.h"
00005 #include "cusb.h"
00006 #include "cphidgetlist.h"
00007 
00008 #if defined(_MACOSX) && !defined(_IPHONE)
00009 #include "macusb.h"
00010 #endif
00011 
00012 CThread_func_return_t CentralThreadFunction(CThread_func_arg_t arg);
00013 
00014 static CThread CentralThread;
00015 static int checkForDevicesEventInitialized = PFALSE;
00016 static EVENT checkForDevicesEvent;
00017 
00018 /* used by OSX to pause traffic during sleep */
00019 int pause_usb_traffic = PFALSE;
00020 int usb_write_paused = PFALSE;
00021 int usb_read_paused = PFALSE;
00022 
00023 #ifdef _MACOSX
00024 void macPeriodicTimerFunction(CFRunLoopTimerRef timer, void *Handle);
00025 void macFindActiveDevicesSource(void *nothing);
00026 CFRunLoopTimerRef timer = NULL;
00027 CFRunLoopSourceRef findActiveDevicesSource = NULL;
00028 #endif
00029 
00030 #ifdef _WINDOWS
00031 
00032 #if defined(_WINDOWS) && !defined(WINCE)
00033 extern void initializeThreadSecurityAttributes();
00034 #else
00035 #define initializeThreadSecurityAttributes()
00036 #endif
00037 extern PSECURITY_ATTRIBUTES pSA;
00038 
00039 #endif
00040 
00041 int
00042 StartCentralThread()
00043 {
00044 
00045 #ifdef _WINDOWS
00046         if (CentralThread.m_ThreadHandle) {
00047                 int threadStatus = 0;
00048                 int result = 0;
00049                 result = GetExitCodeThread(CentralThread.m_ThreadHandle,
00050                     (LPDWORD)&threadStatus);
00051                 if (result) {
00052                         if (threadStatus != STILL_ACTIVE) {
00053                                 CloseHandle(CentralThread.m_ThreadHandle);
00054                                 CentralThread.m_ThreadHandle = 0;
00055                         }
00056                 }
00057         }
00058 #endif
00059 
00060         if(checkForDevicesEventInitialized == PFALSE)
00061         {
00062                 checkForDevicesEventInitialized = PTRUE;
00063                 CThread_create_event(&checkForDevicesEvent);
00064         }
00065         
00066 #ifdef _MACOSX
00067         if(findActiveDevicesSource == NULL)
00068         {
00069                 CFRunLoopSourceContext sourceContext = {0};
00070                 sourceContext.perform = macFindActiveDevicesSource;
00071                 findActiveDevicesSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sourceContext);
00072         }
00073         if(timer == NULL)
00074                 timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 0.250, 0, 0, macPeriodicTimerFunction, NULL);
00075 #endif
00076 
00077         //start the thread
00078         if (!CentralThread.m_ThreadHandle || CentralThread.thread_status == FALSE)
00079         {
00080 #ifdef _MACOSX
00081                 CentralThread.macInitDone = PFALSE;
00082 #endif
00083                 CThread_reset_event(&checkForDevicesEvent);
00084 
00085                 if (CThread_create(&CentralThread, CentralThreadFunction, 0))
00086                         return EPHIDGET_UNEXPECTED;
00087                 CentralThread.thread_status = TRUE;
00088         }
00089         //if it was already running, signal it to check for device matches NOW
00090         else {
00091 #ifdef _MACOSX
00092                 //make sure mac thread stuff is initialized
00093                 while(!CentralThread.macInitDone)
00094                         SLEEP(10);
00095                 //run findActiveDevices in the context of the central thread
00096                 CFRunLoopSourceSignal(findActiveDevicesSource);
00097                 CFRunLoopWakeUp(CentralThread.runLoop);
00098 #else
00099                 //signal thread to poll and findActiveDevices
00100                 CThread_set_event(&checkForDevicesEvent);
00101 #endif
00102         }
00103         return EPHIDGET_OK;
00104 }
00105 
00106 int
00107 JoinCentralThread()
00108 {
00109         if(CentralThread.m_ThreadHandle && !CThread_is_my_thread(CentralThread))
00110         {
00111 #ifdef _MACOSX
00112                 while(!CentralThread.macInitDone)
00113                         SLEEP(10);
00114                 CPhidgetManager_teardownNotifications();
00115                 
00116                 CFRunLoopRemoveTimer(CentralThread.runLoop, timer, kCFRunLoopDefaultMode);
00117                 CFRunLoopRemoveSource(CentralThread.runLoop, findActiveDevicesSource, kCFRunLoopDefaultMode);
00118                 
00119                 CFRunLoopStop(CentralThread.runLoop);
00120                 
00121                 CentralThread.macInitDone = PFALSE;
00122 #endif
00123                 CThread_join(&CentralThread);
00124                 CentralThread.m_ThreadHandle = 0;
00125         }
00126         return EPHIDGET_OK;
00127 }
00128 
00129 /*
00130  * registers a device to receive events and be polled by the central
00131  * thread This needs to start the central thread if it's not yet
00132  * running.
00133 */
00134 int
00135 RegisterLocalDevice(CPhidgetHandle phid)
00136 {
00137         int result;
00138 
00139         TESTPTR(phid)
00140         
00141         if(!phidgetLocksInitialized)
00142         {
00143                 CThread_mutex_init(&activeDevicesLock);
00144                 CThread_mutex_init(&attachedDevicesLock);
00145                 phidgetLocksInitialized = PTRUE;
00146         }
00147         CThread_mutex_lock(&activeDevicesLock);
00148         
00149         if(phid->specificDevice == PHIDGETOPEN_SERIAL || phid->specificDevice == PHIDGETOPEN_LABEL)
00150                 result = CList_addToList((CListHandle *)&ActiveDevices, phid, CPhidget_areEqual);
00151         else
00152                 result = CList_addToList((CListHandle *)&ActiveDevices, phid, CPhidgetHandle_areEqual);
00153 
00154         if (result)
00155         {
00156                 CThread_mutex_unlock(&activeDevicesLock);
00157                 return result;
00158         }
00159         CThread_mutex_unlock(&activeDevicesLock);
00160 
00161         result = StartCentralThread();
00162         return result;
00163 }
00164 
00165 #ifdef _MACOSX
00166 //this is run every 250ms from the CentralThread runLoop
00167 void macPeriodicTimerFunction(CFRunLoopTimerRef timer, void *Handle) {
00168         CPhidgetList *trav = 0;
00169         
00170         //looks for any devices that have set PHIDGET_USB_ERROR_FLAG and reenumerate them
00171         CThread_mutex_lock(&activeDevicesLock);
00172         for (trav=ActiveDevices; trav; trav = trav->next)
00173         {       
00174                 if(CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
00175                 {
00176                         if(CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_USB_ERROR_FLAG))
00177                         {
00178                                 LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a reenumeration.");
00179                                 reenumerateDevice(trav->phid);
00180                         }
00181                 }
00182         }
00183         CThread_mutex_unlock(&activeDevicesLock);
00184         
00185         //need to always keep checking because a device could be opened by another app
00186         //and we want to notice when it becomes accessible.
00187         if(ActiveDevices) {
00188                 findActiveDevices(); //this looks for attached active devices and opens them
00189         }
00190         
00191         return;
00192 }
00193 
00194 //This is run when a new Phidget is registered when the CentralThread is already running
00195 void macFindActiveDevicesSource(void *nothing) {
00196         if(ActiveDevices) {
00197                 findActiveDevices(); //this looks for attached active devices and opens them
00198         }
00199         return;
00200 }
00201 #endif
00202 
00203 //The central thread should stop itself when there are no more active devices...? 
00204 //Or we can stop it in unregisterlocaldevice
00205 
00206 CThread_func_return_t CentralThreadFunction(CThread_func_arg_t lpdwParam)
00207 {
00208 #ifdef _MACOSX
00209         CentralThread.runLoop = CFRunLoopGetCurrent();
00210 
00211         CFRunLoopAddTimer(CentralThread.runLoop, timer, kCFRunLoopDefaultMode);
00212         CFRunLoopAddSource(CentralThread.runLoop, findActiveDevicesSource, kCFRunLoopDefaultMode);
00213         
00214         CentralThread.macInitDone = PTRUE;
00215         
00216         //setup notifications of Phidget attach/detach
00217         CPhidgetManager_setupNotifications(CentralThread.runLoop);
00218         
00219         //start run loop - note that this blocks until JoinCentralThread() is called.
00220         CFRunLoopRun();
00221 #else
00222         //loop as long as there are active devices, or a phidget manager
00223         while(ActiveDevices || ActivePhidgetManagers) {
00224                 CPhidgetManager_poll(); //this will update the list, as well as sending out attach and detach events
00225                 findActiveDevices(); //this looks for attached active devices and opens them
00226 
00227                 //Wait for signal of newly registered device, or 250ms
00228                 //we don't really care about the reason so we don't check the return value
00229                 CThread_wait_on_event(&checkForDevicesEvent, 250);
00230                 CThread_reset_event(&checkForDevicesEvent);
00231         }
00232 #endif
00233 
00234         //if we actually get here, it means there are no active devices, and no phidgetmanagers, so free up the
00235         //last of the memory we are using, and exit the thread...
00236         CThread_mutex_lock(&attachedDevicesLock);
00237         CList_emptyList((CListHandle *)&AttachedDevices, TRUE, CPhidget_free);
00238         CThread_mutex_unlock(&attachedDevicesLock);
00239         
00240         LOG(PHIDGET_LOG_INFO,"Central Thread exiting");
00241         
00242         if(fptrJavaDetachCurrentThread)
00243                 fptrJavaDetachCurrentThread();
00244         CentralThread.thread_status = FALSE;
00245         return EPHIDGET_OK;
00246 }
00247 
00248 //The read thread
00249 CThread_func_return_t ReadThreadFunction(CThread_func_arg_t lpdwParam)
00250 {
00251         CPhidgetHandle phid = (CPhidgetHandle)lpdwParam;
00252         int result = EPHIDGET_OK;
00253         LOG(PHIDGET_LOG_INFO,"ReadThread running");
00254         
00255         if (!phid)
00256         {
00257                 LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - Invalid device handle");
00258                 return (CThread_func_return_t)EPHIDGET_INVALIDARG;
00259         }
00260         
00261         //quit read thread if it's not needed
00262         switch(phid->deviceID)
00263         {
00264                 case PHIDCLASS_SERVO:
00265                         if(phid->deviceVersion < 313)
00266                                 goto exit_not_needed;
00267                         break;
00268                 case PHIDCLASS_INTERFACEKIT:
00269                         if(phid->deviceIDSpec == PHIDID_INTERFACEKIT_0_0_4 && phid->deviceVersion < 704)
00270                                 goto exit_not_needed;
00271                         break;
00272                 case PHIDCLASS_LED:
00273                         if(phid->deviceIDSpec == PHIDID_LED_64)
00274                                 goto exit_not_needed;
00275                         break;
00276                 case PHIDCLASS_TEXTLCD:
00277                         if(phid->deviceIDSpec != PHIDID_TEXTLCD_ADAPTER)
00278                                 goto exit_not_needed;
00279                         break;
00280                 case PHIDCLASS_TEXTLED:
00281 exit_not_needed:
00282                         LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Not Needed for this device)");
00283                         goto exit;
00284                 default:
00285                         break;
00286         }
00287 
00288         while (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
00289         {
00290                 if(pause_usb_traffic)
00291                 {
00292                         usb_read_paused = PTRUE;
00293                         SLEEP(20);
00294                         continue;
00295                 }
00296                 else
00297                         usb_read_paused = PFALSE;
00298                 
00299                 result=CPhidget_read(phid);
00300 
00301                 switch(result)
00302                 {
00303                         case EPHIDGET_OK:
00304                         case EPHIDGET_TRYAGAIN:
00305                                 break;
00306                         case EPHIDGET_NOTATTACHED:
00307                                 LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Phidget detach detected in CPhidget_read)");
00308                                 goto exit;
00309                         case EPHIDGET_INTERRUPTED:
00310                                 LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (signaled by CPhidget_close)");
00311                                 goto exit;
00312                         case EPHIDGET_TIMEOUT:
00313                                 //Set the error flag for devices that should never have a USB timeout, then exit
00314                                 //continue for devices where it is ok
00315                                 switch(phid->deviceID)
00316                                 {
00317                                 case PHIDCLASS_INTERFACEKIT:
00318                                         switch(phid->deviceIDSpec)
00319                                         {
00320                                         case PHIDID_INTERFACEKIT_0_16_16:
00321                                                 if(phid->deviceVersion >= 601)
00322                                                         goto timeout_not_ok;
00323                                                 else
00324                                                         goto timeout_ok;
00325                                         case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
00326                                                 goto timeout_ok;
00327                                         default:
00328                                                 goto timeout_not_ok;
00329                                         }
00330                                 case PHIDCLASS_RFID:
00331                                         if(phid->deviceVersion >= 201)
00332                                                 goto timeout_not_ok;
00333                                         else
00334                                                 goto timeout_ok;
00335                                 case PHIDCLASS_ENCODER:
00336                                         if(phid->deviceIDSpec == PHIDID_ENCODER_HS_4ENCODER_4INPUT)
00337                                                 goto timeout_not_ok;
00338                                         else
00339                                                 goto timeout_ok;
00340                                 case PHIDCLASS_GENERIC:
00341                                         goto timeout_ok;
00342                                 default:
00343                                         goto timeout_not_ok;
00344                                 }
00345                         timeout_not_ok:
00346                                 CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
00347                                 LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - unexpected timeout (could be an ESD event)");
00348                                 goto exit;
00349                         timeout_ok:
00350                                 LOG(PHIDGET_LOG_VERBOSE,"CUSBReadPacket expected time out"); //verbose because it could happen a LOT
00351                                 break;
00352                         case EPHIDGET_UNEXPECTED:
00353                         default:
00354                                 LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - CPhidget_read returned : %d",result);
00355                                 CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
00356                                 goto exit;
00357                 }
00358         }
00359 
00360         LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Phidget detached)");
00361 exit:
00362         if(fptrJavaDetachCurrentThread)
00363                 fptrJavaDetachCurrentThread();
00364         phid->readThread.thread_status = FALSE;
00365         return (CThread_func_return_t)(size_t)result;
00366 }
00367 
00368 //The write thread
00369 CThread_func_return_t WriteThreadFunction(CThread_func_arg_t lpdwParam)
00370 {
00371         CPhidgetHandle phid = (CPhidgetHandle)lpdwParam;
00372         int result = EPHIDGET_OK, wait_return = 0;
00373         LOG(PHIDGET_LOG_INFO,"WriteThread running");
00374 
00375         if (!phid)
00376         {
00377                 LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - Invalid device handle");
00378                 return (CThread_func_return_t)EPHIDGET_INVALIDARG;
00379         }
00380 
00381         //quit write thread if it's not needed
00382         switch(phid->deviceID)
00383         {
00384         case PHIDCLASS_INTERFACEKIT:
00385                 if(phid->deviceIDSpec == PHIDID_LINEAR_TOUCH
00386                         || phid->deviceIDSpec == PHIDID_ROTARY_TOUCH)
00387                         goto exit_not_needed;
00388                 break;
00389         case PHIDCLASS_RFID:
00390                 if(phid->deviceIDSpec == PHIDID_RFID)
00391                         goto exit_not_needed;
00392                 break;
00393         case PHIDCLASS_ENCODER:
00394                 if(phid->deviceIDSpec == PHIDID_ENCODER_1ENCODER_1INPUT
00395                         || phid->deviceIDSpec == PHIDID_ENCODER_HS_1ENCODER)
00396                         goto exit_not_needed;
00397                 break;
00398         case PHIDCLASS_ACCELEROMETER:
00399         case PHIDCLASS_TEMPERATURESENSOR:
00400         case PHIDCLASS_PHSENSOR:
00401         case PHIDCLASS_WEIGHTSENSOR:
00402 exit_not_needed:
00403                 LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Not Needed for this device)");
00404                 goto exit;
00405         default:
00406                 break;
00407         }
00408 
00409         while (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
00410         {
00411                 //if awdc_enabled is true, then we timeout in 200ms and do a write, otherwise no timeout
00412                 wait_return = CThread_wait_on_event(&phid->writeAvailableEvent, 200);
00413                 switch (wait_return) {
00414                 case WAIT_TIMEOUT:
00415                         //putting this in the timeout so actual writes are not missed.
00416                         if(phid->writeStopFlag) 
00417                         {
00418                                 LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (signaled by writeStopFlag)");
00419                                 goto exit;
00420                         }
00421                         if(!phid->awdc_enabled) //only fall through to writting out if awdc is set
00422                                 break;
00423                 case WAIT_OBJECT_0: //writeAvailable
00424                         if(pause_usb_traffic)
00425                         {
00426                                 usb_write_paused = PTRUE;
00427                                 break;
00428                         }
00429                         else
00430                                 usb_write_paused = PFALSE;
00431                                         
00432                         if((result = CPhidget_write(phid)))
00433                         {
00434                                 switch(result)
00435                                 {
00436                                 case EPHIDGET_NOTATTACHED:
00437                                         LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Phidget detach detected in CPhidget_write)");
00438                                         break;
00439                                 case EPHIDGET_INTERRUPTED:
00440                                         LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (signaled by CPhidget_close)");
00441                                         break;
00442                                 case EPHIDGET_TIMEOUT:
00443                                         LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - unexpected timeout (could be an ESD event)");
00444                                         CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
00445                                         break;
00446                                 case EPHIDGET_UNEXPECTED:
00447                                 default:
00448                                         LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - CPhidget_write returned : %d",result);
00449                                         CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
00450                                         break;
00451                                 }
00452                                 goto exit;
00453                         }
00454                         break;
00455                 default:
00456                         LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - wait on phid->writeAvailableEvent failed");
00457                         CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
00458                         result = EPHIDGET_UNEXPECTED;
00459                         goto exit;
00460                 }
00461         }
00462         LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Phidget detached)");
00463 
00464 exit:
00465         if(fptrJavaDetachCurrentThread)
00466                 fptrJavaDetachCurrentThread();
00467         phid->writeStopFlag = FALSE;
00468         phid->writeThread.thread_status = FALSE;
00469         return (CThread_func_return_t)(size_t)result;
00470 }
00471 
00472 int
00473 CThread_create(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg)
00474 {
00475 #ifdef _WINDOWS
00476         initializeThreadSecurityAttributes();
00477         cp->m_ThreadHandle = CreateThread(pSA, 0, (LPTHREAD_START_ROUTINE)fp, arg, 0, &cp->m_ThreadIdentifier);
00478         if(cp->m_ThreadHandle) return EPHIDGET_OK;
00479         else return GetLastError();
00480 #else
00481         return pthread_create(&cp->m_ThreadHandle, NULL, fp, arg);
00482 #endif
00483 }
00484 
00485 int
00486 CThread_create_detached(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg)
00487 {
00488 #ifdef _WINDOWS
00489         cp->m_ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fp, arg, 0, &cp->m_ThreadIdentifier);
00490         if(cp->m_ThreadHandle) return EPHIDGET_OK;
00491         else return GetLastError();
00492 #else
00493         pthread_attr_t attr;
00494         int err;
00495         if((err = pthread_attr_init(&attr)) == 0)
00496         {
00497                 if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) == 0)
00498                 {
00499                         return pthread_create(&cp->m_ThreadHandle, &attr, fp, arg);
00500                 }
00501                 else
00502                 {
00503                         LOG(PHIDGET_LOG_ERROR, "pthread_attr_setdetachstate failed with error: %d",err);
00504                         return err;
00505                 }
00506         }
00507         else
00508         {
00509                 LOG(PHIDGET_LOG_ERROR, "pthread_attr_init failed with error: %d",err);
00510                 return err;
00511         }
00512 #endif
00513 }
00514 
00515 int
00516 CThread_is_my_thread(CThread cp)
00517 {
00518 #ifdef _WINDOWS
00519         return (cp.m_ThreadIdentifier == GetCurrentThreadId());
00520 #else
00521         return pthread_equal(cp.m_ThreadHandle, pthread_self());
00522 #endif
00523 }
00524 
00525 void
00526 CThread_join(CThread *cp)
00527 {
00528 #ifdef _WINDOWS
00529         DWORD ec;
00530 
00531         while (GetExitCodeThread(cp->m_ThreadHandle, &ec) && ec == STILL_ACTIVE)
00532                 SLEEP(10);
00533         CloseHandle(cp->m_ThreadHandle);
00534         cp->m_ThreadHandle = NULL;
00535 
00536 #else
00537         if (cp->thread_status == TRUE)
00538                 pthread_join(cp->m_ThreadHandle, 0);
00539 #endif
00540 }
00541 
00542 /*void
00543 CThread_kill(CThread *cp)
00544 {
00545 #ifdef _WINDOWS
00546         TerminateThread(cp->m_ThreadHandle, 0);
00547 #else
00548         pthread_cancel(cp->m_ThreadHandle);
00549 #endif
00550 }*/
00551 
00552 int
00553 CThread_mutex_init(CThread_mutex_t *mp)
00554 {
00555 #ifdef _WINDOWS
00556         InitializeCriticalSection(mp);
00557         return 1;
00558 #else
00559         return pthread_mutex_init(mp, NULL) == 0;
00560 #endif
00561 }
00562 
00563 int
00564 CThread_mutex_destroy(CThread_mutex_t *mp)
00565 {
00566 #ifdef _WINDOWS
00567         DeleteCriticalSection(mp);
00568         return 1;
00569 #else
00570         return pthread_mutex_destroy(mp) == 0;
00571 #endif
00572 }
00573 
00574 void
00575 CThread_mutex_lock(CThread_mutex_t *mp)
00576 {
00577 #ifdef _WINDOWS
00578         EnterCriticalSection(mp);
00579 #else
00580         pthread_mutex_lock(mp);
00581 #endif
00582 }
00583 
00584 void
00585 CThread_mutex_unlock(CThread_mutex_t *mp)
00586 {
00587 #ifdef _WINDOWS
00588         LeaveCriticalSection(mp);
00589 #else
00590         pthread_mutex_unlock(mp);
00591 #endif
00592 }
00593 
00594 void CThread_create_event(EVENT *ev)
00595 {
00596 #ifdef _WINDOWS
00597         *ev = CreateEvent(NULL, FALSE, FALSE, NULL);
00598 #else
00599     pthread_mutex_init(&ev->mutex, NULL);
00600     pthread_cond_init(&ev->condition, NULL);
00601         ev->ready_to_go = PFALSE;
00602 #endif
00603 }
00604 
00605 int CThread_destroy_event(EVENT *ev)
00606 {
00607 #ifdef _WINDOWS
00608         return CloseHandle(*ev);
00609 #else
00610     if(pthread_mutex_destroy(&ev->mutex)) return 0;
00611     if(pthread_cond_destroy(&ev->condition)) return 0;
00612         return 1;
00613 #endif
00614 }
00615 
00616 int CThread_wait_on_event(EVENT *ev, EVENT_TIME time)
00617 {
00618 #ifdef _WINDOWS
00619         return WaitForSingleObject(*ev, time);
00620 #else
00621         int retval;
00622         struct timespec timeout;
00623         struct timeval now;
00624         
00625     // Lock the mutex.
00626     pthread_mutex_lock(&ev->mutex);
00627  
00628     // If the predicate is already set, then the while loop is bypassed;
00629     // otherwise, the thread sleeps until the predicate is set.
00630     if(ev->ready_to_go == PFALSE)
00631     {
00632                 if(time == INFINITE)
00633                         retval = pthread_cond_wait(&ev->condition, &ev->mutex);
00634                 else {
00635                         gettimeofday(&now,0);
00636                         timeout.tv_sec = now.tv_sec + time/1000;
00637                         timeout.tv_nsec = now.tv_usec*1000 + (time%1000 * 1000000);
00638                         if(timeout.tv_nsec >= 1000000000)
00639                         {
00640                                 timeout.tv_sec++;
00641                                 timeout.tv_nsec -= 1000000000;
00642                         }
00643                         retval = pthread_cond_timedwait(&ev->condition, &ev->mutex, &timeout);
00644                 }
00645                 
00646                 switch(retval)
00647                 {
00648                         case ETIMEDOUT:
00649                                 pthread_mutex_unlock(&ev->mutex); 
00650                                 return WAIT_TIMEOUT;
00651                         case 0:
00652                                 pthread_mutex_unlock(&ev->mutex); 
00653                                 return WAIT_OBJECT_0;
00654                         case EINVAL:
00655                                 pthread_mutex_unlock(&ev->mutex); 
00656                                 return WAIT_FAILED;
00657                         default:
00658                                 pthread_mutex_unlock(&ev->mutex); 
00659                                 return WAIT_FAILED;
00660                 }
00661     }
00662         pthread_mutex_unlock(&ev->mutex); 
00663         return WAIT_OBJECT_0;
00664 #endif
00665 }
00666 
00667 void CThread_reset_event(EVENT *ev)
00668 {
00669 #ifdef _WINDOWS
00670         ResetEvent(*ev);
00671 #else
00672     // Reset the predicate and release the mutex.
00673     pthread_mutex_lock(&ev->mutex);
00674     ev->ready_to_go = PFALSE;
00675     pthread_mutex_unlock(&ev->mutex); 
00676 #endif
00677 }
00678 
00679 void CThread_set_event(EVENT *ev)
00680 {
00681 #ifdef _WINDOWS
00682         SetEvent(*ev);
00683 #else
00684     // At this point, there should be work for the other thread to do.
00685     pthread_mutex_lock(&ev->mutex);
00686     ev->ready_to_go = PTRUE;
00687     // Signal the other thread to begin work.
00688     pthread_cond_signal(&ev->condition);
00689     pthread_mutex_unlock(&ev->mutex);
00690  
00691 #endif
00692 }
00693 


pedal_monitor
Author(s): Pedro Mendes
autogenerated on Fri Jun 6 2014 18:37:21