C++ Rest SDK
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
pplxlinux.h
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 * Linux 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 
29 #if (defined(_MSC_VER))
30 #error This file must not be included for Visual Studio
31 #endif
32 
33 #ifndef _WIN32
34 
35 #include <signal.h>
36 #include "pthread.h"
37 #include "cpprest/details/cpprest_compat.h"
38 
39 #if defined(__APPLE__)
40 #include <dispatch/dispatch.h>
41 #include <boost/thread/mutex.hpp>
42 #include <boost/thread/condition_variable.hpp>
43 #else
44 #include <mutex>
45 #include <condition_variable>
46 #endif
47 
48 #include "pplx/pplxinterface.h"
49 
50 
51 namespace pplx
52 {
53 #if defined(__APPLE__)
54  namespace cpprest_synchronization = ::boost;
55 #else
56  namespace cpprest_synchronization = ::std;
57 #endif
58 namespace details
59 {
60 namespace platform
61 {
65  _PPLXIMP long _pplx_cdecl GetCurrentThreadId();
66 
70  _PPLXIMP void _pplx_cdecl YieldExecution();
71 
75  __declspec(noinline) inline static size_t CaptureCallstack(void **, size_t, size_t)
76  {
77  return 0;
78  }
79 }
80 
84  class event_impl
85  {
86  private:
87  cpprest_synchronization::mutex _lock;
88  cpprest_synchronization::condition_variable _condition;
89  bool _signaled;
90  public:
91 
92  static const unsigned int timeout_infinite = 0xFFFFFFFF;
93 
94  event_impl()
95  : _signaled(false)
96  {
97  }
98 
99  void set()
100  {
101  cpprest_synchronization::lock_guard<cpprest_synchronization::mutex> lock(_lock);
102  _signaled = true;
103  _condition.notify_all();
104  }
105 
106  void reset()
107  {
108  cpprest_synchronization::lock_guard<cpprest_synchronization::mutex> lock(_lock);
109  _signaled = false;
110  }
111 
112  unsigned int wait(unsigned int timeout)
113  {
114  cpprest_synchronization::unique_lock<cpprest_synchronization::mutex> lock(_lock);
115  if (timeout == event_impl::timeout_infinite)
116  {
117  _condition.wait(lock, [this]() -> bool { return _signaled; });
118  return 0;
119  }
120  else
121  {
122  cpprest_synchronization::chrono::milliseconds period(timeout);
123  auto status = _condition.wait_for(lock, period, [this]() -> bool { return _signaled; });
124  _ASSERTE(status == _signaled);
125  // Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite
126  // Note: this must be consistent with the behavior of the Windows version, which is based on WaitForSingleObjectEx
127  return status ? 0: event_impl::timeout_infinite;
128  }
129  }
130 
131  unsigned int wait()
132  {
133  return wait(event_impl::timeout_infinite);
134  }
135  };
136 
141  {
142  private:
143 
144  pthread_rwlock_t _M_reader_writer_lock;
145 
146  public:
147 
149  {
150  public:
151  explicit scoped_lock_read(reader_writer_lock_impl &_Reader_writer_lock) : _M_reader_writer_lock(_Reader_writer_lock)
152  {
153  _M_reader_writer_lock.lock_read();
154  }
155 
157  {
158  _M_reader_writer_lock.unlock();
159  }
160 
161  private:
162  reader_writer_lock_impl& _M_reader_writer_lock;
163  scoped_lock_read(const scoped_lock_read&); // no copy constructor
164  scoped_lock_read const & operator=(const scoped_lock_read&); // no assignment operator
165  };
166 
168  {
169  pthread_rwlock_init(&_M_reader_writer_lock, nullptr);
170  }
171 
173  {
174  pthread_rwlock_destroy(&_M_reader_writer_lock);
175  }
176 
177  void lock()
178  {
179  pthread_rwlock_wrlock(&_M_reader_writer_lock);
180  }
181 
182  void lock_read()
183  {
184  pthread_rwlock_rdlock(&_M_reader_writer_lock);
185  }
186 
187  void unlock()
188  {
189  pthread_rwlock_unlock(&_M_reader_writer_lock);
190  }
191  };
192 
197  {
198  public:
199 
201  : _M_owner(-1), _M_recursionCount(0)
202  {
203  }
204 
206  {
207  _ASSERTE(_M_owner == -1);
208  _ASSERTE(_M_recursionCount == 0);
209  }
210 
211  void lock()
212  {
213  auto id = ::pplx::details::platform::GetCurrentThreadId();
214 
215  if ( _M_owner == id )
216  {
217  _M_recursionCount++;
218  }
219  else
220  {
221  _M_cs.lock();
222  _M_owner = id;
223  _M_recursionCount = 1;
224  }
225  }
226 
227  void unlock()
228  {
229  _ASSERTE(_M_owner == ::pplx::details::platform::GetCurrentThreadId());
230  _ASSERTE(_M_recursionCount >= 1);
231 
232  _M_recursionCount--;
233 
234  if ( _M_recursionCount == 0 )
235  {
236  _M_owner = -1;
237  _M_cs.unlock();
238  }
239  }
240 
241  private:
242  cpprest_synchronization::mutex _M_cs;
243  volatile long _M_owner;
244  long _M_recursionCount;
245  };
246 
247 #if defined(__APPLE__)
248  class apple_scheduler : public pplx::scheduler_interface
249 #else
250  class linux_scheduler : public pplx::scheduler_interface
251 #endif
252  {
253  public:
254  _PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param);
255  };
256 
257 } // namespace details
258 
263 template<class _Lock>
265 {
266 public:
267  explicit scoped_lock(_Lock& _Critical_section) : _M_critical_section(_Critical_section)
268  {
269  _M_critical_section.lock();
270  }
271 
272  ~scoped_lock()
273  {
274  _M_critical_section.unlock();
275  }
276 
277 private:
278  _Lock& _M_critical_section;
279 
280  scoped_lock(const scoped_lock&); // no copy constructor
281  scoped_lock const & operator=(const scoped_lock&); // no assignment operator
282 };
283 
284 // The extensibility namespace contains the type definitions that are used internally
285 namespace extensibility
286 {
287  typedef ::pplx::details::event_impl event_t;
288 
289  typedef cpprest_synchronization::mutex critical_section_t;
290  typedef scoped_lock<critical_section_t> scoped_critical_section_t;
291 
292  typedef ::pplx::details::reader_writer_lock_impl reader_writer_lock_t;
293  typedef scoped_lock<reader_writer_lock_t> scoped_rw_lock_t;
294  typedef ::pplx::extensibility::reader_writer_lock_t::scoped_lock_read scoped_read_lock_t;
295 
296  typedef ::pplx::details::recursive_lock_impl recursive_lock_t;
297  typedef scoped_lock<recursive_lock_t> scoped_recursive_lock_t;
298 }
299 
303 #if defined(__APPLE__)
304  typedef details::apple_scheduler default_scheduler_t;
305 #else
307 #endif
308 
309 namespace details
310 {
314  #ifndef _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
315  #define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() do { \
316  raise(SIGTRAP); \
317  std::terminate(); \
318  } while(false)
319  #endif //_REPORT_PPLTASK_UNOBSERVED_EXCEPTION
320 }
321 
322 //see: http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
323 // this is critical to inline
324 __attribute__ ((always_inline))
325 inline void* _ReturnAddress() { return __builtin_return_address(0); }
326 
327 } // namespace pplx
328 
329 #endif // !_WIN32
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
Definition: pplxlinux.h:250
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
Recursive mutex
Definition: pplxlinux.h:196
Manual reset event
Definition: pplxlinux.h:84
Reader writer lock
Definition: pplxlinux.h:140
details::linux_scheduler default_scheduler_t
Default scheduler type
Definition: pplxlinux.h:306