1 // Copyright 2013 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.
5 #include "mojo/system/waiter.h"
9 #include "base/logging.h"
10 #include "base/time/time.h"
21 awake_result_(MOJO_RESULT_INTERNAL),
22 awake_context_(static_cast<uint32_t>(-1)) {
33 // NOTE(vtl): If performance ever becomes an issue, we can disable the setting
34 // of |awake_result_| (except the first one in |Awake()|) in Release builds.
35 awake_result_ = MOJO_RESULT_INTERNAL;
38 // TODO(vtl): Fast-path the |deadline == 0| case?
39 MojoResult Waiter::Wait(MojoDeadline deadline, uint32_t* context) {
40 base::AutoLock locker(lock_);
44 // It'll need to be re-initialized after this.
48 // Fast-path the already-awoken case:
50 DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
52 *context = awake_context_;
56 // |MojoDeadline| is actually a |uint64_t|, but we need a signed quantity.
57 // Treat any out-of-range deadline as "forever" (which is wrong, but okay
58 // since 2^63 microseconds is ~300000 years). Note that this also takes care
59 // of the |MOJO_DEADLINE_INDEFINITE| (= 2^64 - 1) case.
60 if (deadline > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
65 // NOTE(vtl): This is very inefficient on POSIX, since pthreads condition
66 // variables take an absolute deadline.
67 const base::TimeTicks end_time =
68 base::TimeTicks::Now() +
69 base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline));
71 base::TimeTicks now_time = base::TimeTicks::Now();
72 if (now_time >= end_time)
73 return MOJO_RESULT_DEADLINE_EXCEEDED;
75 cv_.TimedWait(end_time - now_time);
79 DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
81 *context = awake_context_;
85 void Waiter::Awake(MojoResult result, uint32_t context) {
86 base::AutoLock locker(lock_);
92 awake_result_ = result;
93 awake_context_ = context;
95 // |cv_.Wait()|/|cv_.TimedWait()| will return after |lock_| is released.