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