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