1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * ==--==
17 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18 *
19 * Windows specific pplx implementations
20 *
21 * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22 *
23 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24 ****/
25
26 #pragma once
27
28 #if !defined(_WIN32) || _MSC_VER < 1800 || CPPREST_FORCE_PPLX
29
30 #include "cpprest/details/cpprest_compat.h"
31 #include "pplx/pplxinterface.h"
32
34 {
35
36 namespace details
37 {
38 namespace platform
39 {
43 _PPLXIMP long __cdecl GetCurrentThreadId();
44
48 _PPLXIMP void __cdecl YieldExecution();
49
53 __declspec(noinline) _PPLXIMP
size_t __cdecl CaptureCallstack(
void **,
size_t,
size_t);
54
55 #if defined(__cplusplus_winrt)
56 // Internal API which retrieves the next async id.
59 _PPLXIMP unsigned int __cdecl GetNextAsyncId();
60 #endif
61 }
62
66 class event_impl
67 {
68 public:
69
70 static const unsigned int timeout_infinite = 0xFFFFFFFF;
71
72 _PPLXIMP event_impl();
73
74 _PPLXIMP ~event_impl();
75
76 _PPLXIMP void set();
77
78 _PPLXIMP void reset();
79
80 _PPLXIMP unsigned int wait(unsigned int timeout);
81
82 unsigned int wait()
83 {
84 return wait(event_impl::timeout_infinite);
85 }
86
87 private:
88 // Windows events
89 void * _M_impl;
90
91 event_impl(const event_impl&); // no copy constructor
92 event_impl const & operator=(const event_impl&); // no assignment operator
93 };
94
99 {
100 public:
101
103
104 _PPLXIMP ~critical_section_impl();
105
106 _PPLXIMP void lock();
107
108 _PPLXIMP void unlock();
109
110 private:
111
112 typedef void * _PPLX_BUFFER;
113
114 // Windows critical section
115 _PPLX_BUFFER _M_impl[8];
116
117 critical_section_impl(const critical_section_impl&); // no copy constructor
118 critical_section_impl const & operator=(const critical_section_impl&); // no assignment operator
119 };
120
121 #if _WIN32_WINNT >= _WIN32_WINNT_VISTA
126 {
127 public:
128
129 class scoped_lock_read
130 {
131 public:
132 explicit scoped_lock_read(
reader_writer_lock_impl &_Reader_writer_lock) : _M_reader_writer_lock(_Reader_writer_lock)
133 {
134 _M_reader_writer_lock.lock_read();
135 }
136
137 ~scoped_lock_read()
138 {
139 _M_reader_writer_lock.unlock();
140 }
141
142 private:
143 reader_writer_lock_impl& _M_reader_writer_lock;
144 scoped_lock_read(const scoped_lock_read&); // no copy constructor
145 scoped_lock_read const & operator=(const scoped_lock_read&); // no assignment operator
146 };
147
148 _PPLXIMP reader_writer_lock_impl();
149
150 _PPLXIMP void lock();
151
152 _PPLXIMP void lock_read();
153
154 _PPLXIMP void unlock();
155
156 private:
157
158 // Windows slim reader writer lock
159 void * _M_impl;
160
161 // Slim reader writer lock doesn't have a general 'unlock' method.
162 // We need to track how it was acquired and release accordingly.
163 // true - lock exclusive
164 // false - lock shared
165 bool m_locked_exclusive;
166 };
167 #endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA
168
172 class recursive_lock_impl
173 {
174 public:
175
176 recursive_lock_impl()
177 : _M_owner(-1), _M_recursionCount(0)
178 {
179 }
180
181 ~recursive_lock_impl()
182 {
183 _ASSERTE(_M_owner == -1);
184 _ASSERTE(_M_recursionCount == 0);
185 }
186
187 void recursive_lock_impl::lock()
188 {
189 auto id = ::pplx::details::platform::GetCurrentThreadId();
190
191 if ( _M_owner == id )
192 {
193 _M_recursionCount++;
194 }
195 else
196 {
197 _M_cs.lock();
198 _M_owner = id;
199 _M_recursionCount = 1;
200 }
201 }
202
203 void recursive_lock_impl::unlock()
204 {
205 _ASSERTE(_M_owner == ::pplx::details::platform::GetCurrentThreadId());
206 _ASSERTE(_M_recursionCount >= 1);
207
208 _M_recursionCount--;
209
210 if ( _M_recursionCount == 0 )
211 {
212 _M_owner = -1;
213 _M_cs.unlock();
214 }
215 }
216
217 private:
219 long _M_recursionCount;
220 volatile long _M_owner;
221 };
222
224 {
225 public:
226 _PPLXIMP
virtual void schedule(
TaskProc_t proc, _In_
void* param);
227 };
228
229 } // namespace details
230
235 template<class _Lock>
237 {
238 public:
239 explicit scoped_lock(_Lock& _Critical_section) : _M_critical_section(_Critical_section)
240 {
241 _M_critical_section.lock();
242 }
243
244 ~scoped_lock()
245 {
246 _M_critical_section.unlock();
247 }
248
249 private:
250 _Lock& _M_critical_section;
251
252 scoped_lock(const scoped_lock&); // no copy constructor
253 scoped_lock const & operator=(const scoped_lock&); // no assignment operator
254 };
255
256 // The extensibility namespace contains the type definitions that are used internally
257 namespace extensibility
258 {
259 typedef ::pplx::details::event_impl event_t;
260
261 typedef ::pplx::details::critical_section_impl critical_section_t;
262 typedef scoped_lock<critical_section_t> scoped_critical_section_t;
263
264 #if _WIN32_WINNT >= _WIN32_WINNT_VISTA
265 typedef ::pplx::details::reader_writer_lock_impl reader_writer_lock_t;
266 typedef scoped_lock<reader_writer_lock_t> scoped_rw_lock_t;
267 typedef reader_writer_lock_t::scoped_lock_read scoped_read_lock_t;
268 #endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA
269
270
271 typedef ::pplx::details::recursive_lock_impl recursive_lock_t;
272 typedef scoped_lock<recursive_lock_t> scoped_recursive_lock_t;
273 }
274
279
280 namespace details
281 {
285
286 #ifndef _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
287 #define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() do { \
288 __debugbreak(); \
289 std::terminate(); \
290 } while(false)
291 #endif // _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
292
293 } // namespace details
294
295 } // namespace pplx
296
297 #endif
void(_pplx_cdecl * TaskProc_t)(void *)
An elementary abstraction for a task, defined as void (__cdecl * TaskProc_t)(void *)...
Definition: pplxinterface.h:59
A generic RAII wrapper for locks that implements the critical_section interface cpprest_synchronizati...
Definition: pplxlinux.h:264
The pplx namespace provides classes and functions that give you access to the Concurrency Runtime...
Definition: pplx.h:81
struct __declspec(novtable) scheduler_interface
Scheduler Interface
Definition: pplxinterface.h:64
Definition: pplxwin.h:223
Mutex - lock for mutual exclusion
Definition: pplxwin.h:98
Reader writer lock
Definition: pplxlinux.h:140
details::linux_scheduler default_scheduler_t
Default scheduler type
Definition: pplxlinux.h:306