14ee2ad04344446e610172a0e73949212923014dfSebastian Redl/* 22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Copyright 2004 The WebRTC Project Authors. All rights reserved. 32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * 42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Use of this source code is governed by a BSD-style license 52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * that can be found in the LICENSE file in the root of the source 62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * tree. An additional intellectual property rights grant can be found 72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * in the file PATENTS. All contributing project authors may 82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * be found in the AUTHORS file in the root of the source tree. 92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor */ 10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl 112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "webrtc/base/event.h" 122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#if defined(WEBRTC_WIN) 147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include <windows.h> 15e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#elif defined(WEBRTC_POSIX) 16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include <pthread.h> 172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <sys/time.h> 182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <time.h> 192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#else 200b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor#error "Must define either WEBRTC_WIN or WEBRTC_POSIX." 212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif 22a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall 236ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redlnamespace rtc { 247c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner 256a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor#if defined(WEBRTC_WIN) 267c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner 2783d63c78810556d26b62ac4cbae2eda6cdd2570cSteve NaroffEvent::Event(bool manual_reset, bool initially_signaled) 2814f79002e58556798e86168c63e48d533287eda5Douglas Gregor : is_manual_reset_(manual_reset), 293251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor is_initially_signaled_(initially_signaled) { 3014f79002e58556798e86168c63e48d533287eda5Douglas Gregor event_handle_ = ::CreateEvent(NULL, // Security attributes. 31bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor is_manual_reset_, 322bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor is_initially_signaled_, 33ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor NULL); // Name. 3417fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor ASSERT(event_handle_ != NULL); 3517fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor} 362596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar 372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorEvent::~Event() { 3814f79002e58556798e86168c63e48d533287eda5Douglas Gregor CloseHandle(event_handle_); 39b64c19365deab788753d29c9bc881253c3f16f37Douglas Gregor} 403c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner 412cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid Event::Set() { 428538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl SetEvent(event_handle_); 432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 44ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl 45ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redlvoid Event::Reset() { 46ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl ResetEvent(event_handle_); 47ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl} 48ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl 49ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redlbool Event::Wait(int cms) { 50ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl DWORD ms = (cms == kForever)? INFINITE : cms; 51ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0); 52ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl} 532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#elif defined(WEBRTC_POSIX) 552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 5612b1c7615d4f9a2edc544be499f895f16ac100edChris LattnerEvent::Event(bool manual_reset, bool initially_signaled) 572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor : is_manual_reset_(manual_reset), 583397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl event_status_(initially_signaled) { 59a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl VERIFY(pthread_mutex_init(&event_mutex_, NULL) == 0); 60a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl VERIFY(pthread_cond_init(&event_cond_, NULL) == 0); 612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorEvent::~Event() { 648538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl pthread_mutex_destroy(&event_mutex_); 652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_cond_destroy(&event_cond_); 663397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 678538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid Event::Set() { 692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_mutex_lock(&event_mutex_); 702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor event_status_ = true; 712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_cond_broadcast(&event_cond_); 722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_mutex_unlock(&event_mutex_); 732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid Event::Reset() { 762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_mutex_lock(&event_mutex_); 772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor event_status_ = false; 782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_mutex_unlock(&event_mutex_); 793397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorbool Event::Wait(int cms) { 822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor pthread_mutex_lock(&event_mutex_); 833397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl int error = 0; 842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 858538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl if (cms != kForever) { 862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Converting from seconds and microseconds (1e-6) plus 872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // milliseconds (1e-3) to seconds and nanoseconds (1e-9). 883397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor struct timespec ts; 908538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Use relative time version, which tends to be more efficient for 922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // pthread implementations where provided (like on Android). 933397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl ts.tv_sec = cms / 1000; 941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ts.tv_nsec = (cms % 1000) * 1000000; 958538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#else 962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor struct timeval tv; 972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor gettimeofday(&tv, NULL); 983397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ts.tv_sec = tv.tv_sec + (cms / 1000); 1008538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl ts.tv_nsec = tv.tv_usec * 1000 + (cms % 1000) * 1000000; 1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Handle overflow. 1033397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl if (ts.tv_nsec >= 1000000000) { 1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ts.tv_sec++; 1058538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl ts.tv_nsec -= 1000000000; 1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif 1083397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump while (!event_status_ && error == 0) { 1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 1118538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl error = pthread_cond_timedwait_relative_np( 1122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor &event_cond_, &event_mutex_, &ts); 1132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#else 1143397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts); 1152cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif 1162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1170953e767ff7817f97b3ab20896b229891eeff45bJohn McCall } else { 1182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor while (!event_status_ && error == 0) 1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor error = pthread_cond_wait(&event_cond_, &event_mutex_); 1203397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 1212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // NOTE(liulk): Exactly one thread will auto-reset this event. All 1238538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // the other threads will think it's unsignaled. This seems to be 1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // consistent with auto-reset events in WEBRTC_WIN 1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (error == 0 && !is_manual_reset_) 1263397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl event_status_ = false; 1272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1288538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl pthread_mutex_unlock(&event_mutex_); 1292cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return (error == 0); 1313397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 1322cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1337e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor#endif 1347e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor 135c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor} // namespace rtc 1368538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl