Home | History | Annotate | Download | only in synchronization
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/synchronization/condition_variable.h"
      6 
      7 #include <errno.h>
      8 #include <sys/time.h>
      9 
     10 #include "base/logging.h"
     11 #include "base/synchronization/lock.h"
     12 #include "base/time.h"
     13 
     14 namespace base {
     15 
     16 ConditionVariable::ConditionVariable(Lock* user_lock)
     17     : user_mutex_(user_lock->lock_.os_lock())
     18 #if !defined(NDEBUG)
     19     , user_lock_(user_lock)
     20 #endif
     21 {
     22   int rv = pthread_cond_init(&condition_, NULL);
     23   DCHECK_EQ(0, rv);
     24 }
     25 
     26 ConditionVariable::~ConditionVariable() {
     27   int rv = pthread_cond_destroy(&condition_);
     28   DCHECK_EQ(0, rv);
     29 }
     30 
     31 void ConditionVariable::Wait() {
     32 #if !defined(NDEBUG)
     33   user_lock_->CheckHeldAndUnmark();
     34 #endif
     35   int rv = pthread_cond_wait(&condition_, user_mutex_);
     36   DCHECK_EQ(0, rv);
     37 #if !defined(NDEBUG)
     38   user_lock_->CheckUnheldAndMark();
     39 #endif
     40 }
     41 
     42 void ConditionVariable::TimedWait(const TimeDelta& max_time) {
     43   int64 usecs = max_time.InMicroseconds();
     44 
     45   // The timeout argument to pthread_cond_timedwait is in absolute time.
     46   struct timeval now;
     47   gettimeofday(&now, NULL);
     48 
     49   struct timespec abstime;
     50   abstime.tv_sec = now.tv_sec + (usecs / Time::kMicrosecondsPerSecond);
     51   abstime.tv_nsec = (now.tv_usec + (usecs % Time::kMicrosecondsPerSecond)) *
     52                     Time::kNanosecondsPerMicrosecond;
     53   abstime.tv_sec += abstime.tv_nsec / Time::kNanosecondsPerSecond;
     54   abstime.tv_nsec %= Time::kNanosecondsPerSecond;
     55   DCHECK_GE(abstime.tv_sec, now.tv_sec);  // Overflow paranoia
     56 
     57 #if !defined(NDEBUG)
     58   user_lock_->CheckHeldAndUnmark();
     59 #endif
     60   int rv = pthread_cond_timedwait(&condition_, user_mutex_, &abstime);
     61   DCHECK(rv == 0 || rv == ETIMEDOUT);
     62 #if !defined(NDEBUG)
     63   user_lock_->CheckUnheldAndMark();
     64 #endif
     65 }
     66 
     67 void ConditionVariable::Broadcast() {
     68   int rv = pthread_cond_broadcast(&condition_);
     69   DCHECK_EQ(0, rv);
     70 }
     71 
     72 void ConditionVariable::Signal() {
     73   int rv = pthread_cond_signal(&condition_);
     74   DCHECK_EQ(0, rv);
     75 }
     76 
     77 }  // namespace base
     78