Line data Source code
1 : /*
2 : * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/base/event.h"
12 :
13 : #if defined(WEBRTC_WIN)
14 : #include <windows.h>
15 : #elif defined(WEBRTC_POSIX)
16 : #include <pthread.h>
17 : #include <sys/time.h>
18 : #include <time.h>
19 : #else
20 : #error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
21 : #endif
22 :
23 : #include "webrtc/base/checks.h"
24 :
25 : namespace rtc {
26 :
27 : #if defined(WEBRTC_WIN)
28 :
29 : Event::Event(bool manual_reset, bool initially_signaled) {
30 : event_handle_ = ::CreateEvent(NULL, // Security attributes.
31 : manual_reset,
32 : initially_signaled,
33 : NULL); // Name.
34 : RTC_CHECK(event_handle_);
35 : }
36 :
37 : Event::~Event() {
38 : CloseHandle(event_handle_);
39 : }
40 :
41 : void Event::Set() {
42 : SetEvent(event_handle_);
43 : }
44 :
45 : void Event::Reset() {
46 : ResetEvent(event_handle_);
47 : }
48 :
49 : bool Event::Wait(int milliseconds) {
50 : DWORD ms = (milliseconds == kForever) ? INFINITE : milliseconds;
51 : return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
52 : }
53 :
54 : #elif defined(WEBRTC_POSIX)
55 :
56 0 : Event::Event(bool manual_reset, bool initially_signaled)
57 : : is_manual_reset_(manual_reset),
58 0 : event_status_(initially_signaled) {
59 0 : RTC_CHECK(pthread_mutex_init(&event_mutex_, NULL) == 0);
60 0 : RTC_CHECK(pthread_cond_init(&event_cond_, NULL) == 0);
61 0 : }
62 :
63 0 : Event::~Event() {
64 0 : pthread_mutex_destroy(&event_mutex_);
65 0 : pthread_cond_destroy(&event_cond_);
66 0 : }
67 :
68 0 : void Event::Set() {
69 0 : pthread_mutex_lock(&event_mutex_);
70 0 : event_status_ = true;
71 0 : pthread_cond_broadcast(&event_cond_);
72 0 : pthread_mutex_unlock(&event_mutex_);
73 0 : }
74 :
75 0 : void Event::Reset() {
76 0 : pthread_mutex_lock(&event_mutex_);
77 0 : event_status_ = false;
78 0 : pthread_mutex_unlock(&event_mutex_);
79 0 : }
80 :
81 0 : bool Event::Wait(int milliseconds) {
82 0 : int error = 0;
83 :
84 : struct timespec ts;
85 0 : if (milliseconds != kForever) {
86 : // Converting from seconds and microseconds (1e-6) plus
87 : // milliseconds (1e-3) to seconds and nanoseconds (1e-9).
88 :
89 : #ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
90 : // Use relative time version, which tends to be more efficient for
91 : // pthread implementations where provided (like on Android).
92 : ts.tv_sec = milliseconds / 1000;
93 : ts.tv_nsec = (milliseconds % 1000) * 1000000;
94 : #else
95 : struct timeval tv;
96 0 : gettimeofday(&tv, NULL);
97 :
98 0 : ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
99 0 : ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;
100 :
101 : // Handle overflow.
102 0 : if (ts.tv_nsec >= 1000000000) {
103 0 : ts.tv_sec++;
104 0 : ts.tv_nsec -= 1000000000;
105 : }
106 : #endif
107 : }
108 :
109 0 : pthread_mutex_lock(&event_mutex_);
110 0 : if (milliseconds != kForever) {
111 0 : while (!event_status_ && error == 0) {
112 : #ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
113 : error = pthread_cond_timedwait_relative_np(
114 : &event_cond_, &event_mutex_, &ts);
115 : #else
116 0 : error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
117 : #endif
118 : }
119 : } else {
120 0 : while (!event_status_ && error == 0)
121 0 : error = pthread_cond_wait(&event_cond_, &event_mutex_);
122 : }
123 :
124 : // NOTE(liulk): Exactly one thread will auto-reset this event. All
125 : // the other threads will think it's unsignaled. This seems to be
126 : // consistent with auto-reset events in WEBRTC_WIN
127 0 : if (error == 0 && !is_manual_reset_)
128 0 : event_status_ = false;
129 :
130 0 : pthread_mutex_unlock(&event_mutex_);
131 :
132 0 : return (error == 0);
133 : }
134 :
135 : #endif
136 :
137 : } // namespace rtc
|