1 /* 2 * Copyright (c) 2011 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 "condition_variable_posix.h" 12 13 #if defined(WEBRTC_LINUX) 14 #include <ctime> 15 #else 16 #include <sys/time.h> 17 #endif 18 19 #include <errno.h> 20 21 #include "critical_section_posix.h" 22 23 namespace webrtc { 24 ConditionVariableWrapper* ConditionVariablePosix::Create() 25 { 26 ConditionVariablePosix* ptr = new ConditionVariablePosix; 27 if (!ptr) 28 { 29 return NULL; 30 } 31 32 const int error = ptr->Construct(); 33 if (error) 34 { 35 delete ptr; 36 return NULL; 37 } 38 39 return ptr; 40 } 41 42 ConditionVariablePosix::ConditionVariablePosix() 43 { 44 } 45 46 int ConditionVariablePosix::Construct() 47 { 48 int result = 0; 49 #ifdef WEBRTC_CLOCK_TYPE_REALTIME 50 result = pthread_cond_init(&_cond, NULL); 51 #else 52 pthread_condattr_t condAttr; 53 result = pthread_condattr_init(&condAttr); 54 if (result != 0) 55 { 56 return -1; 57 } 58 result = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC); 59 if (result != 0) 60 { 61 return -1; 62 } 63 result = pthread_cond_init(&_cond, &condAttr); 64 if (result != 0) 65 { 66 return -1; 67 } 68 result = pthread_condattr_destroy(&condAttr); 69 if (result != 0) 70 { 71 return -1; 72 } 73 #endif 74 return 0; 75 } 76 77 ConditionVariablePosix::~ConditionVariablePosix() 78 { 79 pthread_cond_destroy(&_cond); 80 } 81 82 void ConditionVariablePosix::SleepCS(CriticalSectionWrapper& critSect) 83 { 84 CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>( 85 &critSect); 86 pthread_cond_wait(&_cond, &cs->_mutex); 87 } 88 89 90 bool 91 ConditionVariablePosix::SleepCS( 92 CriticalSectionWrapper& critSect, 93 unsigned long maxTimeInMS) 94 { 95 const unsigned long INFINITE = 0xFFFFFFFF; 96 97 const int MILLISECONDS_PER_SECOND = 1000; 98 #ifndef WEBRTC_LINUX 99 const int MICROSECONDS_PER_MILLISECOND = 1000; 100 #endif 101 const int NANOSECONDS_PER_SECOND = 1000000000; 102 const int NANOSECONDS_PER_MILLISECOND = 1000000; 103 104 CriticalSectionPosix* cs = reinterpret_cast<CriticalSectionPosix*>( 105 &critSect); 106 107 if (maxTimeInMS != INFINITE) 108 { 109 timespec ts; 110 #ifndef WEBRTC_MAC 111 #ifdef WEBRTC_CLOCK_TYPE_REALTIME 112 clock_gettime(CLOCK_REALTIME, &ts); 113 #else 114 clock_gettime(CLOCK_MONOTONIC, &ts); 115 #endif 116 #else 117 struct timeval tv; 118 gettimeofday(&tv, 0); 119 ts.tv_sec = tv.tv_sec; 120 ts.tv_nsec = tv.tv_usec * MICROSECONDS_PER_MILLISECOND; 121 #endif 122 123 ts.tv_sec += maxTimeInMS / MILLISECONDS_PER_SECOND; 124 ts.tv_nsec += (maxTimeInMS - ((maxTimeInMS / MILLISECONDS_PER_SECOND)* 125 MILLISECONDS_PER_SECOND)) * NANOSECONDS_PER_MILLISECOND; 126 127 if (ts.tv_nsec >= NANOSECONDS_PER_SECOND) 128 { 129 ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; 130 ts.tv_nsec %= NANOSECONDS_PER_SECOND; 131 } 132 const int res = pthread_cond_timedwait(&_cond, &cs->_mutex, &ts); 133 return (res == ETIMEDOUT) ? false : true; 134 } 135 else 136 { 137 pthread_cond_wait(&_cond, &cs->_mutex); 138 return true; 139 } 140 } 141 142 void ConditionVariablePosix::Wake() 143 { 144 pthread_cond_signal(&_cond); 145 } 146 147 void ConditionVariablePosix::WakeAll() 148 { 149 pthread_cond_broadcast(&_cond); 150 } 151 } // namespace webrtc 152