16e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org/*
26e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
36e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *
46e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
56e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
66e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
76e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
86e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
96e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org */
106e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
116e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
126e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org#include "webrtc/system_wrappers/source/condition_variable_native_win.h"
136e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org#include "webrtc/system_wrappers/source/critical_section_win.h"
146e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
156e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgnamespace webrtc {
166e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
176e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgstatic HMODULE library = NULL;
18c6f71c55ec3aa886689c78bb0f84d07473aca137wu@webrtc.orgstatic bool win_support_condition_variables_primitive = false;
196e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
206e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgPInitializeConditionVariable  PInitializeConditionVariable_;
216e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgPSleepConditionVariableCS     PSleepConditionVariableCS_;
226e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgPWakeConditionVariable        PWakeConditionVariable_;
236e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgPWakeAllConditionVariable     PWakeAllConditionVariable_;
246e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
256e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgtypedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
266e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgtypedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
276e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org                                                 PCRITICAL_SECTION, DWORD);
286e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgtypedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
296e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgtypedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
306e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
316e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgConditionVariableNativeWin::ConditionVariableNativeWin() {
326e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
336e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
346e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgConditionVariableNativeWin::~ConditionVariableNativeWin() {
356e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
366e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
376e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgConditionVariableWrapper* ConditionVariableNativeWin::Create() {
386e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin();
396e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  if (!ret_val->Init()) {
406e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    delete ret_val;
416e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    return NULL;
426e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  }
436e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  return ret_val;
446e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
456e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
466e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgbool ConditionVariableNativeWin::Init() {
476e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  if (!library) {
486e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    // Native implementation is supported on Vista+.
496e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    library = LoadLibrary(TEXT("Kernel32.dll"));
506e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    // TODO(henrike): this code results in an attempt to load the above dll
516e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    // every time the previous attempt failed. Only try to load once.
526e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    if (library) {
536e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      // TODO(henrike): not thread safe as reading and writing to library is not
546e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      // serialized. Fix.
556e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
566e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
576e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      PInitializeConditionVariable_ =
586e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org          (PInitializeConditionVariable) GetProcAddress(
596e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org              library, "InitializeConditionVariable");
606e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
616e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org          library, "SleepConditionVariableCS");
626e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
636e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org          library, "WakeConditionVariable");
646e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
656e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org          library, "WakeAllConditionVariable");
666e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
676e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
686e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org          && PWakeConditionVariable_ && PWakeAllConditionVariable_) {
696e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org        WEBRTC_TRACE(
706e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org            kTraceStateInfo, kTraceUtility, -1,
716e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org            "Loaded native condition variables");
7214e22dde27f94d3275cfff53abe0556516e04061wu@webrtc.org        win_support_condition_variables_primitive = true;
736e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      }
746e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    }
756e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  }
766e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  if (!win_support_condition_variables_primitive) {
776e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org    return false;
786e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  }
796e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  PInitializeConditionVariable_(&condition_variable_);
806e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  return true;
816e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
826e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
836e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgvoid ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) {
846e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  SleepCS(crit_sect, INFINITE);
856e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
866e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
876e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgbool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect,
886e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org                                         unsigned long max_time_in_ms) {
896e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  CriticalSectionWindows* cs =
906e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org      static_cast<CriticalSectionWindows*>(&crit_sect);
916e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_,
926e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org                                            &(cs->crit), max_time_in_ms);
936e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  return ret_val != 0;
946e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
956e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
966e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgvoid ConditionVariableNativeWin::Wake() {
976e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  PWakeConditionVariable_(&condition_variable_);
986e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
996e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
1006e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.orgvoid ConditionVariableNativeWin::WakeAll() {
1016e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org  PWakeAllConditionVariable_(&condition_variable_);
1026e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}
1036e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org
1046e34ceb97c11f4d390742a8364e77a65b8a01200henrike@webrtc.org}  // namespace webrtc
105