blob: 643ead3f052d724eff880a45b87822bb25bbd95e [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/synchronization/waitable_event.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/trace_event/base_tracing.h"
namespace base {
void WaitableEvent::Signal() {
// Must be ordered before SignalImpl() to guarantee it's emitted before the
// matching TerminatingFlow in TimedWait().
if (!only_used_while_idle_) {
TRACE_EVENT_INSTANT("wakeup.flow", "WaitableEvent::Signal",
perfetto::Flow::FromPointer(this));
}
SignalImpl();
}
void WaitableEvent::Wait() {
const bool result = TimedWait(TimeDelta::Max());
DCHECK(result) << "TimedWait() should never fail with infinite timeout";
}
bool WaitableEvent::TimedWait(TimeDelta wait_delta) {
if (wait_delta <= TimeDelta())
return IsSignaled();
// Consider this thread blocked for scheduling purposes. Ignore this for
// non-blocking WaitableEvents.
absl::optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
scoped_blocking_call;
if (!only_used_while_idle_) {
scoped_blocking_call.emplace(FROM_HERE, BlockingType::MAY_BLOCK);
}
const bool result = TimedWaitImpl(wait_delta);
if (result && !only_used_while_idle_) {
TRACE_EVENT_INSTANT("wakeup.flow", "WaitableEvent::Wait Complete",
perfetto::TerminatingFlow::FromPointer(this));
}
return result;
}
} // namespace base