1 /***
2  * Copyright (C) Microsoft. All rights reserved.
3  * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4  *
5  * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
6  *
7  * Parallel Patterns Library
8  *
9  * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
10  *
11  * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
12  ****/
13 
14 #pragma once
15 
16 #ifndef _PPLX_H
17 #define _PPLX_H
18 
19 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
20 #error This file must not be included for Visual Studio 12 or later
21 #endif
22 
23 #ifndef _WIN32
24 #if defined(_WIN32) || defined(__cplusplus_winrt)
25 #define _WIN32
26 #endif
27 #endif // _WIN32
28 
29 #ifdef _NO_PPLXIMP
30 #define _PPLXIMP
31 #else
32 #ifdef _PPLX_EXPORT
33 #define _PPLXIMP __declspec(dllexport)
34 #else
35 #define _PPLXIMP __declspec(dllimport)
36 #endif
37 #endif
38 
39 #include "cpprest/details/cpprest_compat.h"
40 
41 // Use PPLx
42 #ifdef _WIN32
43 #include "pplx/pplxwin.h"
44 #elif defined(__APPLE__)
45 #undef _PPLXIMP
46 #define _PPLXIMP
47 #include "pplx/pplxlinux.h"
48 #else
49 #include "pplx/pplxlinux.h"
50 #endif // _WIN32
51 
52 // Common implementation across all the non-concrt versions
53 #include "pplx/pplxcancellation_token.h"
54 #include <functional>
55 
56 // conditional expression is constant
57 #if defined(_MSC_VER)
58 #pragma warning(push)
59 #pragma warning(disable : 4127)
60 #endif
61 
62 #pragma pack(push, _CRT_PACKING)
63 
64 /// <summary>
65 ///     The <c>pplx</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
66 ///     a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
67 /// </summary>
68 /**/
69 namespace pplx
70 {
71 /// <summary>
72 /// Sets the ambient scheduler to be used by the PPL constructs.
73 /// </summary>
74 _PPLXIMP void _pplx_cdecl set_ambient_scheduler(std::shared_ptr<pplx::scheduler_interface> _Scheduler);
75 
76 /// <summary>
77 /// Gets the ambient scheduler to be used by the PPL constructs
78 /// </summary>
79 _PPLXIMP std::shared_ptr<pplx::scheduler_interface> _pplx_cdecl get_ambient_scheduler();
80 
81 namespace details
82 {
83 //
84 // An internal exception that is used for cancellation. Users do not "see" this exception except through the
85 // resulting stack unwind. This exception should never be intercepted by user code. It is intended
86 // for use by the runtime only.
87 //
88 class _Interruption_exception : public std::exception
89 {
90 public:
_Interruption_exception()91     _Interruption_exception() {}
92 };
93 
94 template<typename _T>
95 struct _AutoDeleter
96 {
_AutoDeleter_AutoDeleter97     _AutoDeleter(_T* _PPtr) : _Ptr(_PPtr) {}
~_AutoDeleter_AutoDeleter98     ~_AutoDeleter() { delete _Ptr; }
99     _T* _Ptr;
100 };
101 
102 struct _TaskProcHandle
103 {
_TaskProcHandle_TaskProcHandle104     _TaskProcHandle() {}
105 
~_TaskProcHandle_TaskProcHandle106     virtual ~_TaskProcHandle() {}
107     virtual void invoke() const = 0;
108 
_RunChoreBridge_TaskProcHandle109     static void _pplx_cdecl _RunChoreBridge(void* _Parameter)
110     {
111         auto _PTaskHandle = static_cast<_TaskProcHandle*>(_Parameter);
112         _AutoDeleter<_TaskProcHandle> _AutoDeleter(_PTaskHandle);
113         _PTaskHandle->invoke();
114     }
115 };
116 
117 enum _TaskInliningMode
118 {
119     // Disable inline scheduling
120     _NoInline = 0,
121     // Let runtime decide whether to do inline scheduling or not
122     _DefaultAutoInline = 16,
123     // Always do inline scheduling
124     _ForceInline = -1,
125 };
126 
127 // This is an abstraction that is built on top of the scheduler to provide these additional functionalities
128 // - Ability to wait on a work item
129 // - Ability to cancel a work item
130 // - Ability to inline work on invocation of RunAndWait
131 class _TaskCollectionImpl
132 {
133 public:
134     typedef _TaskProcHandle _TaskProcHandle_t;
135 
_TaskCollectionImpl(scheduler_ptr _PScheduler)136     _TaskCollectionImpl(scheduler_ptr _PScheduler) : _M_pScheduler(_PScheduler) {}
137 
_ScheduleTask(_TaskProcHandle_t * _PTaskHandle,_TaskInliningMode _InliningMode)138     void _ScheduleTask(_TaskProcHandle_t* _PTaskHandle, _TaskInliningMode _InliningMode)
139     {
140         if (_InliningMode == _ForceInline)
141         {
142             _TaskProcHandle_t::_RunChoreBridge(_PTaskHandle);
143         }
144         else
145         {
146             _M_pScheduler->schedule(_TaskProcHandle_t::_RunChoreBridge, _PTaskHandle);
147         }
148     }
149 
_Cancel()150     void _Cancel()
151     {
152         // No cancellation support
153     }
154 
_RunAndWait()155     void _RunAndWait()
156     {
157         // No inlining support yet
158         _Wait();
159     }
160 
_Wait()161     void _Wait() { _M_Completed.wait(); }
162 
_Complete()163     void _Complete() { _M_Completed.set(); }
164 
_GetScheduler()165     scheduler_ptr _GetScheduler() const { return _M_pScheduler; }
166 
167     // Fire and forget
_RunTask(TaskProc_t _Proc,void * _Parameter,_TaskInliningMode _InliningMode)168     static void _RunTask(TaskProc_t _Proc, void* _Parameter, _TaskInliningMode _InliningMode)
169     {
170         if (_InliningMode == _ForceInline)
171         {
172             _Proc(_Parameter);
173         }
174         else
175         {
176             // Schedule the work on the ambient scheduler
177             get_ambient_scheduler()->schedule(_Proc, _Parameter);
178         }
179     }
180 
_Is_cancellation_requested()181     static bool _pplx_cdecl _Is_cancellation_requested()
182     {
183         // We do not yet have the ability to determine the current task. So return false always
184         return false;
185     }
186 
187 private:
188     extensibility::event_t _M_Completed;
189     scheduler_ptr _M_pScheduler;
190 };
191 
192 // For create_async lambdas that return a (non-task) result, we oversubscriber the current task for the duration of the
193 // lambda.
194 struct _Task_generator_oversubscriber
195 {
196 };
197 
198 typedef _TaskCollectionImpl _TaskCollection_t;
199 typedef _TaskInliningMode _TaskInliningMode_t;
200 typedef _Task_generator_oversubscriber _Task_generator_oversubscriber_t;
201 
202 } // namespace details
203 
204 } // namespace pplx
205 
206 #pragma pack(pop)
207 #if defined(_MSC_VER)
208 #pragma warning(pop)
209 #endif
210 
211 #endif // _PPLX_H
212