| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "SignaledEvent.h"
- #include "RakAssert.h"
- #include "RakSleep.h"
- #if defined(__GNUC__)
- #include <sys/time.h>
- #include <unistd.h>
- #endif
- using namespace RakNet;
- SignaledEvent::SignaledEvent()
- {
- #ifdef _WIN32
- eventList=INVALID_HANDLE_VALUE;
- #else
- isSignaled=false;
- #endif
- }
- SignaledEvent::~SignaledEvent()
- {
- // Intentionally do not close event, so it doesn't close twice on linux
- }
- void SignaledEvent::InitEvent(void)
- {
- #if defined(WINDOWS_PHONE_8) || defined(WINDOWS_STORE_RT)
- eventList=CreateEventEx(0, 0, 0, 0);
- #elif defined(_WIN32)
- eventList=CreateEvent(0, false, false, 0);
- #else
- #if !defined(ANDROID)
- pthread_condattr_init( &condAttr );
- pthread_cond_init(&eventList, &condAttr);
- #else
- pthread_cond_init(&eventList, 0);
- #endif
- pthread_mutexattr_init( &mutexAttr );
- pthread_mutex_init(&hMutex, &mutexAttr);
- #endif
- }
- void SignaledEvent::CloseEvent(void)
- {
- #ifdef _WIN32
- if (eventList!=INVALID_HANDLE_VALUE)
- {
- CloseHandle(eventList);
- eventList=INVALID_HANDLE_VALUE;
- }
- #else
- pthread_cond_destroy(&eventList);
- pthread_mutex_destroy(&hMutex);
- #if !defined(ANDROID)
- pthread_condattr_destroy( &condAttr );
- #endif
- pthread_mutexattr_destroy( &mutexAttr );
- #endif
- }
- void SignaledEvent::SetEvent(void)
- {
- #ifdef _WIN32
- ::SetEvent(eventList);
- #else
- // Different from SetEvent which stays signaled.
- // We have to record manually that the event was signaled
- isSignaledMutex.Lock();
- isSignaled=true;
- isSignaledMutex.Unlock();
- // Unblock waiting threads
- pthread_cond_broadcast(&eventList);
- #endif
- }
- void SignaledEvent::WaitOnEvent(int timeoutMs)
- {
- #ifdef _WIN32
- // WaitForMultipleObjects(
- // 2,
- // eventList,
- // false,
- // timeoutMs);
- WaitForSingleObjectEx(eventList,timeoutMs,FALSE);
- #else
- // If was previously set signaled, just unset and return
- isSignaledMutex.Lock();
- if (isSignaled==true)
- {
- isSignaled=false;
- isSignaledMutex.Unlock();
- return;
- }
- isSignaledMutex.Unlock();
-
- //struct timespec ts;
- // Else wait for SetEvent to be called
- struct timespec ts;
- int rc;
- struct timeval tp;
- rc = gettimeofday(&tp, NULL);
- ts.tv_sec = tp.tv_sec;
- ts.tv_nsec = tp.tv_usec * 1000;
- // #endif
- while (timeoutMs > 30)
- {
- // Wait 30 milliseconds for the signal, then check again.
- // This is in case we missed the signal between the top of this function and pthread_cond_timedwait, or after the end of the loop and pthread_cond_timedwait
- ts.tv_nsec += 30*1000000;
- if (ts.tv_nsec >= 1000000000)
- {
- ts.tv_nsec -= 1000000000;
- ts.tv_sec++;
- }
-
- // [SBC] added mutex lock/unlock around cond_timedwait.
- // this prevents airplay from generating a whole much of errors.
- // not sure how this works on other platforms since according to
- // the docs you are suppost to hold the lock before you wait
- // on the cond.
- pthread_mutex_lock(&hMutex);
- pthread_cond_timedwait(&eventList, &hMutex, &ts);
- pthread_mutex_unlock(&hMutex);
- timeoutMs-=30;
- isSignaledMutex.Lock();
- if (isSignaled==true)
- {
- isSignaled=false;
- isSignaledMutex.Unlock();
- return;
- }
- isSignaledMutex.Unlock();
- }
- // Wait the remaining time, and turn off the signal in case it was set
- ts.tv_nsec += timeoutMs*1000000;
- if (ts.tv_nsec >= 1000000000)
- {
- ts.tv_nsec -= 1000000000;
- ts.tv_sec++;
- }
- pthread_mutex_lock(&hMutex);
- pthread_cond_timedwait(&eventList, &hMutex, &ts);
- pthread_mutex_unlock(&hMutex);
- isSignaledMutex.Lock();
- isSignaled=false;
- isSignaledMutex.Unlock();
- #endif
- }
|