1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/system_wrappers/include/trace.h"
12 #include "webrtc/system_wrappers/source/condition_variable_native_win.h"
13 #include "webrtc/system_wrappers/source/critical_section_win.h"
14 
15 namespace webrtc {
16 
17 static HMODULE library = NULL;
18 static bool win_support_condition_variables_primitive = false;
19 
20 PInitializeConditionVariable  PInitializeConditionVariable_;
21 PSleepConditionVariableCS     PSleepConditionVariableCS_;
22 PWakeConditionVariable        PWakeConditionVariable_;
23 PWakeAllConditionVariable     PWakeAllConditionVariable_;
24 
25 typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
26 typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
27                                                  PCRITICAL_SECTION, DWORD);
28 typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
29 typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
30 
ConditionVariableNativeWin()31 ConditionVariableNativeWin::ConditionVariableNativeWin() {
32 }
33 
~ConditionVariableNativeWin()34 ConditionVariableNativeWin::~ConditionVariableNativeWin() {
35 }
36 
Create()37 ConditionVariableWrapper* ConditionVariableNativeWin::Create() {
38   ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin();
39   if (!ret_val->Init()) {
40     delete ret_val;
41     return NULL;
42   }
43   return ret_val;
44 }
45 
Init()46 bool ConditionVariableNativeWin::Init() {
47   if (!library) {
48     // Native implementation is supported on Vista+.
49     library = LoadLibrary(TEXT("Kernel32.dll"));
50     // TODO(henrike): this code results in an attempt to load the above dll
51     // every time the previous attempt failed. Only try to load once.
52     if (library) {
53       // TODO(henrike): not thread safe as reading and writing to library is not
54       // serialized. Fix.
55       WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
56 
57       PInitializeConditionVariable_ =
58           (PInitializeConditionVariable) GetProcAddress(
59               library, "InitializeConditionVariable");
60       PSleepConditionVariableCS_ = (PSleepConditionVariableCS) GetProcAddress(
61           library, "SleepConditionVariableCS");
62       PWakeConditionVariable_ = (PWakeConditionVariable) GetProcAddress(
63           library, "WakeConditionVariable");
64       PWakeAllConditionVariable_ = (PWakeAllConditionVariable) GetProcAddress(
65           library, "WakeAllConditionVariable");
66 
67       if (PInitializeConditionVariable_ && PSleepConditionVariableCS_
68           && PWakeConditionVariable_ && PWakeAllConditionVariable_) {
69         WEBRTC_TRACE(
70             kTraceStateInfo, kTraceUtility, -1,
71             "Loaded native condition variables");
72         win_support_condition_variables_primitive = true;
73       }
74     }
75   }
76   if (!win_support_condition_variables_primitive) {
77     return false;
78   }
79   PInitializeConditionVariable_(&condition_variable_);
80   return true;
81 }
82 
SleepCS(CriticalSectionWrapper & crit_sect)83 void ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) {
84   SleepCS(crit_sect, INFINITE);
85 }
86 
SleepCS(CriticalSectionWrapper & crit_sect,unsigned long max_time_in_ms)87 bool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect,
88                                          unsigned long max_time_in_ms) {
89   CriticalSectionWindows* cs =
90       static_cast<CriticalSectionWindows*>(&crit_sect);
91   BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_,
92                                             &(cs->crit), max_time_in_ms);
93   return ret_val != 0;
94 }
95 
Wake()96 void ConditionVariableNativeWin::Wake() {
97   PWakeConditionVariable_(&condition_variable_);
98 }
99 
WakeAll()100 void ConditionVariableNativeWin::WakeAll() {
101   PWakeAllConditionVariable_(&condition_variable_);
102 }
103 
104 }  // namespace webrtc
105