chromium/v8/src/base/platform/condition-variable.cc

// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/base/platform/condition-variable.h"

#include <errno.h>
#include <time.h>

#include "src/base/platform/time.h"

#if V8_OS_WIN
#include <windows.h>
#endif

namespace v8 {
namespace base {

#if V8_OS_POSIX

ConditionVariable::ConditionVariable() {}


ConditionVariable::~ConditionVariable() {}


void ConditionVariable::NotifyOne() {}


void ConditionVariable::NotifyAll() {}


void ConditionVariable::Wait(Mutex* mutex) {}


bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {}

#elif V8_OS_WIN

ConditionVariable::ConditionVariable() {
  InitializeConditionVariable(V8ToWindowsType(&native_handle_));
}


ConditionVariable::~ConditionVariable() {}

void ConditionVariable::NotifyOne() {
  WakeConditionVariable(V8ToWindowsType(&native_handle_));
}

void ConditionVariable::NotifyAll() {
  WakeAllConditionVariable(V8ToWindowsType(&native_handle_));
}


void ConditionVariable::Wait(Mutex* mutex) {
  mutex->AssertHeldAndUnmark();
  SleepConditionVariableSRW(V8ToWindowsType(&native_handle_),
                            V8ToWindowsType(&mutex->native_handle()), INFINITE,
                            0);
  mutex->AssertUnheldAndMark();
}


bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
  int64_t msec = rel_time.InMilliseconds();
  mutex->AssertHeldAndUnmark();
  BOOL result = SleepConditionVariableSRW(
      V8ToWindowsType(&native_handle_),
      V8ToWindowsType(&mutex->native_handle()), static_cast<DWORD>(msec), 0);
#ifdef DEBUG
  if (!result) {
    // On failure, we only expect the CV to timeout. Any other error value means
    // that we've unexpectedly woken up.
    // Note that WAIT_TIMEOUT != ERROR_TIMEOUT. WAIT_TIMEOUT is used with the
    // WaitFor* family of functions as a direct return value. ERROR_TIMEOUT is
    // used with GetLastError().
    DCHECK_EQ(static_cast<DWORD>(ERROR_TIMEOUT), GetLastError());
  }
#endif
  mutex->AssertUnheldAndMark();
  return result != 0;
}

#elif V8_OS_STARBOARD

ConditionVariable::ConditionVariable() {
  SbConditionVariableCreate(&native_handle_, nullptr);
}

ConditionVariable::~ConditionVariable() {
  SbConditionVariableDestroy(&native_handle_);
}

void ConditionVariable::NotifyOne() {
  SbConditionVariableSignal(&native_handle_);
}

void ConditionVariable::NotifyAll() {
  SbConditionVariableBroadcast(&native_handle_);
}

void ConditionVariable::Wait(Mutex* mutex) {
  SbConditionVariableWait(&native_handle_, &mutex->native_handle());
}

bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
  int64_t microseconds = static_cast<int64_t>(rel_time.InMicroseconds());
  SbConditionVariableResult result = SbConditionVariableWaitTimed(
      &native_handle_, &mutex->native_handle(), microseconds);
  DCHECK(result != kSbConditionVariableFailed);
  return result == kSbConditionVariableSignaled;
}

#endif  // V8_OS_STARBOARD

}  // namespace base
}  // namespace v8