michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/condition_variable.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/lock.h" michael@0: #include "base/lock_impl.h" michael@0: #include "base/logging.h" michael@0: #include "base/time.h" michael@0: michael@0: using base::Time; michael@0: using base::TimeDelta; michael@0: michael@0: ConditionVariable::ConditionVariable(Lock* user_lock) michael@0: : user_mutex_(user_lock->lock_impl()->os_lock()) { michael@0: int rv = 0; michael@0: #if !defined(OS_MACOSX) && !defined(OS_ANDROID) michael@0: pthread_condattr_t attrs; michael@0: rv = pthread_condattr_init(&attrs); michael@0: DCHECK_EQ(0, rv); michael@0: pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); michael@0: rv = pthread_cond_init(&condition_, &attrs); michael@0: pthread_condattr_destroy(&attrs); michael@0: #else michael@0: rv = pthread_cond_init(&condition_, NULL); michael@0: #endif michael@0: DCHECK_EQ(0, rv); michael@0: } michael@0: michael@0: ConditionVariable::~ConditionVariable() { michael@0: int rv = pthread_cond_destroy(&condition_); michael@0: DCHECK(rv == 0); michael@0: } michael@0: michael@0: void ConditionVariable::Wait() { michael@0: int rv = pthread_cond_wait(&condition_, user_mutex_); michael@0: DCHECK(rv == 0); michael@0: } michael@0: michael@0: void ConditionVariable::TimedWait(const TimeDelta& max_time) { michael@0: int64_t usecs = max_time.InMicroseconds(); michael@0: michael@0: struct timespec relative_time; michael@0: relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond; michael@0: relative_time.tv_nsec = michael@0: (usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond; michael@0: michael@0: #if defined(OS_MACOSX) michael@0: int rv = pthread_cond_timedwait_relative_np( michael@0: &condition_, user_mutex_, &relative_time); michael@0: #else michael@0: // The timeout argument to pthread_cond_timedwait is in absolute time. michael@0: struct timespec now; michael@0: clock_gettime(CLOCK_MONOTONIC, &now); michael@0: michael@0: struct timespec absolute_time; michael@0: absolute_time.tv_sec = now.tv_sec; michael@0: absolute_time.tv_nsec = now.tv_nsec; michael@0: absolute_time.tv_sec += relative_time.tv_sec; michael@0: absolute_time.tv_nsec += relative_time.tv_nsec; michael@0: absolute_time.tv_sec += absolute_time.tv_nsec / Time::kNanosecondsPerSecond; michael@0: absolute_time.tv_nsec %= Time::kNanosecondsPerSecond; michael@0: DCHECK_GE(absolute_time.tv_sec, now.tv_sec); // Overflow paranoia michael@0: michael@0: #if defined(OS_ANDROID) michael@0: int rv = pthread_cond_timedwait_monotonic_np( michael@0: &condition_, user_mutex_, &absolute_time); michael@0: #else michael@0: int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time); michael@0: #endif // OS_ANDROID michael@0: #endif // OS_MACOSX michael@0: michael@0: DCHECK(rv == 0 || rv == ETIMEDOUT); michael@0: } michael@0: michael@0: void ConditionVariable::Broadcast() { michael@0: int rv = pthread_cond_broadcast(&condition_); michael@0: DCHECK(rv == 0); michael@0: } michael@0: michael@0: void ConditionVariable::Signal() { michael@0: int rv = pthread_cond_signal(&condition_); michael@0: DCHECK(rv == 0); michael@0: }