1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 * Modified for native C++ WRL support by Gregory Morse
7 *
8 * ==--==
9 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
10 *
11 * ppltasks_winrt.h
12 *
13 * Parallel Patterns Library - PPL Tasks
14 *
15 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
16 ****/
17 
18 #pragma once
19 
20 #ifndef _PPLTASKS_WINRT_H
21 #define _PPLTASKS_WINRT_H
22 
23 #include <concrt.h>
24 #include <ppltasks.h>
25 #if _MSC_VER >= 1800
26 #include <pplconcrt.h>
27 
28 // Cannot build using a compiler that is older than dev10 SP1
29 #ifdef _MSC_VER
30 #if _MSC_FULL_VER < 160040219 /*IFSTRIP=IGN*/
31 #error ERROR: Visual Studio 2010 SP1 or later is required to build ppltasks
32 #endif /*IFSTRIP=IGN*/
33 #endif
34 #else
35 #include <ppl.h>
36 #endif
37 #include <functional>
38 #include <vector>
39 #include <utility>
40 #include <exception>
41 #if _MSC_VER >= 1800
42 #include <algorithm>
43 #endif
44 
45 #ifndef __cplusplus_winrt
46 
47 #include <wrl\implements.h>
48 #include <wrl\async.h>
49 #if _MSC_VER >= 1800
50 #include "agile_wrl.hpp"
51 #endif
52 #include <windows.foundation.h>
53 #include <ctxtcall.h>
54 
55 #ifndef _UITHREADCTXT_SUPPORT
56 
57 #ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/
58 
59 // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user
60 #include <winapifamily.h>
61 
62 #if WINAPI_FAMILY == WINAPI_FAMILY_APP /*IFSTRIP=IGN*/
63     // UI thread context support is not required for desktop and Windows Store apps
64     #define _UITHREADCTXT_SUPPORT 0
65 #elif WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP /*IFSTRIP=IGN*/
66     // UI thread context support is not required for desktop and Windows Store apps
67     #define _UITHREADCTXT_SUPPORT 0
68 #else  /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
69     #define _UITHREADCTXT_SUPPORT 1
70 #endif  /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
71 
72 #else   /* WINAPI_FAMILY */
73     // Not supported without a WINAPI_FAMILY setting.
74     #define _UITHREADCTXT_SUPPORT 0
75 #endif  /* WINAPI_FAMILY */
76 
77 #endif  /* _UITHREADCTXT_SUPPORT */
78 
79 #if _UITHREADCTXT_SUPPORT
80 #include <uithreadctxt.h>
81 #endif  /* _UITHREADCTXT_SUPPORT */
82 
83 #pragma detect_mismatch("_PPLTASKS_WITH_WINRT", "0")
84 
85 #ifdef _DEBUG
86 #define _DBG_ONLY(X) X
87 #else
88 #define _DBG_ONLY(X)
89 #endif // #ifdef _DEBUG
90 
91 // std::copy_exception changed to std::make_exception_ptr from VS 2010 to VS 11.
92 #ifdef _MSC_VER
93 #if _MSC_VER < 1700 /*IFSTRIP=IGN*/
94 namespace std
95 {
make_exception_ptr(_E _Except)96     template<class _E> exception_ptr make_exception_ptr(_E _Except)
97     {
98         return copy_exception(_Except);
99     }
100 }
101 #endif
102 #ifndef _PPLTASK_ASYNC_LOGGING
103 #if _MSC_VER >= 1800 && defined(__cplusplus_winrt)
104 #define _PPLTASK_ASYNC_LOGGING 1  // Only enable async logging under dev12 winrt
105 #else
106 #define _PPLTASK_ASYNC_LOGGING 0
107 #endif
108 #endif
109 #endif
110 
111 #pragma pack(push,_CRT_PACKING)
112 
113 #pragma warning(push)
114 #pragma warning(disable: 28197)
115 #pragma warning(disable: 4100) // Unreferenced formal parameter - needed for document generation
116 #if _MSC_VER >= 1800
117 #pragma warning(disable: 4127) // constant express in if condition - we use it for meta programming
118 #else
119 #pragma warning(disable: 4702) // Unreachable code - it is caused by user lambda throw exceptions
120 #endif
121 
122 // All CRT public header files are required to be protected from the macro new
123 #pragma push_macro("new")
124 #undef new
125 
126 // stuff ported from Dev11 CRT
127 // NOTE: this doesn't actually match std::declval. it behaves differently for void!
128 // so don't blindly change it to std::declval.
129 namespace stdx
130 {
131     template<class _T>
132     _T&& declval();
133 }
134 
135 /// <summary>
136 ///     The <c>Concurrency_winrt</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
137 ///     a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
138 /// </summary>
139 /**/
140 namespace Concurrency_winrt
141 {
142     // In debug builds, default to 10 frames, unless this is overridden prior to #includ'ing ppltasks.h.  In retail builds, default to only one frame.
143 #ifndef PPL_TASK_SAVE_FRAME_COUNT
144 #ifdef _DEBUG
145 #define PPL_TASK_SAVE_FRAME_COUNT 10
146 #else
147 #define PPL_TASK_SAVE_FRAME_COUNT 1
148 #endif
149 #endif
150 
151     /// <summary>
152     /// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified,
153     /// only one frame is captured and no stackwalk will be involved. Otherwise, the number of callstack frames will be captured.
154     /// </summary>
155     /// <ramarks>
156     /// This needs to be defined as a macro rather than a function so that if we're only gathering one frame, _ReturnAddress()
157     /// will evaluate to client code, rather than a helper function inside of _TaskCreationCallstack, itself.
158     /// </remarks>
159 #ifdef _CAPTURE_CALLSTACK
160 #undef _CAPTURE_CALLSTACK
161 #endif
162 #if PPL_TASK_SAVE_FRAME_COUNT > 1
163 #if !defined(_DEBUG)
164 #pragma message ("WARNING: Redefinning PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!")
165 #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
166 #else
167 #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPL_TASK_SAVE_FRAME_COUNT)
168 #endif
169 #else
170 #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
171 #endif
172 /// <summary>
173 
174 ///     A type that represents the terminal state of a task. Valid values are <c>completed</c> and <c>canceled</c>.
175 /// </summary>
176 /// <seealso cref="task Class"/>
177 /**/
178 typedef Concurrency::task_group_status task_status;
179 
180 template <typename _Type> class task;
181 template <> class task<void>;
182 
183 /// <summary>
184 ///     Returns an indication of whether the task that is currently executing has received a request to cancel its
185 ///     execution. Cancellation is requested on a task if the task was created with a cancellation token, and
186 ///     the token source associated with that token is canceled.
187 /// </summary>
188 /// <returns>
189 ///     <c>true</c> if the currently executing task has received a request for cancellation, <c>false</c> otherwise.
190 /// </returns>
191 /// <remarks>
192 ///     If you call this method in the body of a task and it returns <c>true</c>, you must respond with a call to
193 ///     <see cref="cancel_current_task Function">cancel_current_task</see> to acknowledge the cancellation request,
194 ///     after performing any cleanup you need. This will abort the execution of the task and cause it to enter into
195 ///     the <c>canceled</c> state. If you do not respond and continue execution, or return instead of calling
196 ///     <c>cancel_current_task</c>, the task will enter the <c>completed</c> state when it is done.
197 ///     state.
198 ///     <para>A task is not cancellable if it was created without a cancellation token.</para>
199 /// </remarks>
200 /// <seealso cref="task Class"/>
201 /// <seealso cref="cancellation_token_source Class"/>
202 /// <seealso cref="cancellation_token Class"/>
203 /// <seealso cref="cancel_current_task Function"/>
204 /**/
205 #if _MSC_VER >= 1800
is_task_cancellation_requested()206 inline bool __cdecl is_task_cancellation_requested()
207 {
208     return ::Concurrency::details::_TaskCollection_t::_Is_cancellation_requested();
209 }
210 #else
is_task_cancellation_requested()211 inline bool __cdecl is_task_cancellation_requested()
212 {
213     // ConcRT scheduler under the hood is using TaskCollection, which is same as task_group
214     return ::Concurrency::is_current_task_group_canceling();
215 }
216 #endif
217 
218 /// <summary>
219 ///     Cancels the currently executing task. This function can be called from within the body of a task to abort the
220 ///     task's execution and cause it to enter the <c>canceled</c> state. While it may be used in response to
221 ///     the <see cref="is_task_cancellation_requested Function">is_task_cancellation_requested</see> function, you may
222 ///     also use it by itself, to initiate cancellation of the task that is currently executing.
223 ///     <para>It is not a supported scenario to call this function if you are not within the body of a <c>task</c>.
224 ///     Doing so will result in undefined behavior such as a crash or a hang in your application.</para>
225 /// </summary>
226 /// <seealso cref="task Class"/>
227 /// <seealso cref="is_task_cancellation_requested"/>
228 /**/
229 //#if _MSC_VER >= 1800
cancel_current_task()230 inline __declspec(noreturn) void __cdecl cancel_current_task()
231 {
232     throw Concurrency::task_canceled();
233 }
234 //#else
235 //_CRTIMP2 __declspec(noreturn) void __cdecl cancel_current_task();
236 //#endif
237 
238 namespace details
239 {
240 #if _MSC_VER >= 1800
241     /// <summary>
242     ///     Callstack container, which is used to capture and preserve callstacks in ppltasks.
243     ///     Members of this class is examined by vc debugger, thus there will be no public access methods.
244     ///     Please note that names of this class should be kept stable for debugger examining.
245     /// </summary>
246     class _TaskCreationCallstack
247     {
248     private:
249         // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame;
250         // otherwise, _M_Frame will store all the callstack frames.
251         void* _M_SingleFrame;
252         std::vector<void *> _M_frames;
253     public:
_TaskCreationCallstack()254         _TaskCreationCallstack()
255         {
256             _M_SingleFrame = nullptr;
257         }
258 
259         // Store one frame of callstack. This function works for both Debug / Release CRT.
_CaptureSingleFrameCallstack(void * _SingleFrame)260         static _TaskCreationCallstack _CaptureSingleFrameCallstack(void *_SingleFrame)
261         {
262             _TaskCreationCallstack _csc;
263             _csc._M_SingleFrame = _SingleFrame;
264             return _csc;
265         }
266 
267         // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT.
268         __declspec(noinline)
_CaptureMultiFramesCallstack(size_t _CaptureFrames)269             static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames)
270         {
271                 _TaskCreationCallstack _csc;
272                 _csc._M_frames.resize(_CaptureFrames);
273                 // skip 2 frames to make sure callstack starts from user code
274                 _csc._M_frames.resize(::Concurrency::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames));
275                 return _csc;
276         }
277     };
278 #endif
279     typedef UINT32 _Unit_type;
280 
281     struct _TypeSelectorNoAsync {};
282     struct _TypeSelectorAsyncOperationOrTask {};
283     struct _TypeSelectorAsyncOperation : public _TypeSelectorAsyncOperationOrTask { };
284     struct _TypeSelectorAsyncTask : public _TypeSelectorAsyncOperationOrTask { };
285     struct _TypeSelectorAsyncAction {};
286     struct _TypeSelectorAsyncActionWithProgress {};
287     struct _TypeSelectorAsyncOperationWithProgress {};
288 
289     template<typename _Ty>
290     struct _NormalizeVoidToUnitType
291     {
292         typedef _Ty _Type;
293     };
294 
295     template<>
296     struct _NormalizeVoidToUnitType<void>
297     {
298         typedef _Unit_type _Type;
299     };
300 
301     template<typename _T>
302     struct _IsUnwrappedAsyncSelector
303     {
304         static const bool _Value = true;
305     };
306 
307     template<>
308     struct _IsUnwrappedAsyncSelector<_TypeSelectorNoAsync>
309     {
310         static const bool _Value = false;
311     };
312 
313     template <typename _Ty>
314     struct _UnwrapTaskType
315     {
316         typedef _Ty _Type;
317     };
318 
319     template <typename _Ty>
320     struct _UnwrapTaskType<task<_Ty>>
321     {
322         typedef _Ty _Type;
323     };
324 
325     template <typename _T>
326     _TypeSelectorAsyncTask _AsyncOperationKindSelector(task<_T>);
327 
328     _TypeSelectorNoAsync _AsyncOperationKindSelector(...);
329 
330     template <typename _Type>
331     struct _Unhat
332     {
333         typedef _Type _Value;
334     };
335 
336     template <typename _Type>
337     struct _Unhat<_Type*>
338     {
339         typedef _Type _Value;
340     };
341 
342     //struct _NonUserType { public: int _Dummy; };
343 
344     template <typename _Type, bool _IsValueTypeOrRefType = __is_valid_winrt_type(_Type)>
345     struct _ValueTypeOrRefType
346     {
347         typedef _Unit_type _Value;
348     };
349 
350     template <typename _Type>
351     struct _ValueTypeOrRefType<_Type, true>
352     {
353         typedef _Type _Value;
354     };
355 
356     template <typename _Ty>
357     _Ty _UnwrapAsyncActionWithProgressSelector(ABI::Windows::Foundation::IAsyncActionWithProgress_impl<_Ty>*);
358 
359     template <typename _Ty>
360     _Ty _UnwrapAsyncActionWithProgressSelector(...);
361 
362     template <typename _Ty, typename _Progress>
363     _Progress _UnwrapAsyncOperationWithProgressProgressSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<_Ty, _Progress>*);
364 
365     template <typename _Ty, typename _Progress>
366     _Progress _UnwrapAsyncOperationWithProgressProgressSelector(...);
367 
368     template <typename _T1, typename _T2>
369     _T2 _ProgressTypeSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*);
370 
371     template <typename _T1>
372     _T1 _ProgressTypeSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T1>*);
373 
374     template <typename _Type>
375     struct _GetProgressType
376     {
377         typedef decltype(_ProgressTypeSelector(stdx::declval<_Type>())) _Value;
378     };
379 
380     template <typename _T>
381     _TypeSelectorAsyncOperation _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperation<_T>*);
382 
383     _TypeSelectorAsyncAction _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncAction*);
384 
385     template <typename _T1, typename _T2>
386     _TypeSelectorAsyncOperationWithProgress _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*);
387 
388     template <typename _T>
389     _TypeSelectorAsyncActionWithProgress _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T>*);
390 
391     template <typename _Type>
392     struct _IsIAsyncInfo
393     {
394         static const bool _Value = std::is_base_of<ABI::Windows::Foundation::IAsyncInfo, typename _Unhat<_Type>::_Value>::value ||
395             std::is_same<_TypeSelectorAsyncAction, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value ||
396             std::is_same<_TypeSelectorAsyncOperation, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value ||
397             std::is_same<_TypeSelectorAsyncOperationWithProgress, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value ||
398             std::is_same<_TypeSelectorAsyncActionWithProgress, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value;
399     };
400 
401     template <>
402     struct _IsIAsyncInfo<void>
403     {
404         static const bool _Value = false;
405     };
406 
407     template <typename _Ty>
408     _Ty _UnwrapAsyncOperationSelector(ABI::Windows::Foundation::IAsyncOperation_impl<_Ty>*);
409 
410     template <typename _Ty>
411     _Ty _UnwrapAsyncOperationSelector(...);
412 
413     template <typename _Ty, typename _Progress>
414     _Ty _UnwrapAsyncOperationWithProgressSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<_Ty, _Progress>*);
415 
416     template <typename _Ty, typename _Progress>
417     _Ty _UnwrapAsyncOperationWithProgressSelector(...);
418 
419     // Unwrap functions for asyncOperations
420     template<typename _Ty>
421     auto _GetUnwrappedType(ABI::Windows::Foundation::IAsyncOperation<_Ty>*) -> typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperation<_Ty>*>()))>::type;
422 
423     void _GetUnwrappedType(ABI::Windows::Foundation::IAsyncAction*);
424 
425     template<typename _Ty, typename _Progress>
426     auto _GetUnwrappedType(ABI::Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>*) -> typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>*>()))>::type;
427 
428     template<typename _Progress>
429     void _GetUnwrappedType(ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>*);
430 
431     template <typename _T>
432     _T _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperation<_T>*);
433 
434     void _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncAction*);
435 
436     template <typename _T1, typename _T2>
437     _T1 _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*);
438 
439     template <typename _T>
440     void _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T>*);
441 
442     class _ProgressReporterCtorArgType{};
443 
444     template <typename _Type, bool _IsAsync = _IsIAsyncInfo<_Type>::_Value>
445     struct _TaskTypeTraits
446     {
447         typedef typename details::_UnwrapTaskType<_Type>::_Type _TaskRetType;
448         typedef _TaskRetType _TaskRetType_abi;
449         typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
450         typedef typename details::_NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
451 
452         static const bool _IsAsyncTask = _IsAsync;
453         static const bool _IsUnwrappedTaskOrAsync = details::_IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
454     };
455 
456     template<typename _Type>
457     struct _TaskTypeTraits<_Type, true>
458     {
459         typedef decltype(_ReturnAsyncOperationKindSelector(stdx::declval<_Type>())) _TaskRetType;
460         typedef decltype(_GetUnwrappedType(stdx::declval<_Type>())) _TaskRetType_abi;
461         typedef _TaskRetType _NormalizedTaskRetType;
462         typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
463 
464         static const bool _IsAsyncTask = true;
465         static const bool _IsUnwrappedTaskOrAsync = details::_IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
466     };
467 
_IsCallable(_Function _Func,int,int,int)468     template <typename _ReturnType, typename _Function> auto _IsCallable(_Function _Func, int, int, int) -> decltype(_Func(stdx::declval<task<_ReturnType>*>()), std::true_type()) { (void)_Func; return std::true_type(); }
_IsCallable(_Function _Func,int,int,...)469     template <typename _ReturnType, typename _Function> auto _IsCallable(_Function _Func, int, int, ...) -> decltype(_Func(stdx::declval<_ReturnType*>()), std::true_type()) { (void)_Func; return std::true_type(); }
_IsCallable(_Function _Func,int,...)470     template <typename _ReturnType, typename _Function> auto _IsCallable(_Function _Func, int, ...) -> decltype(_Func(), std::true_type()) { (void)_Func; return std::true_type(); }
_IsCallable(_Function,...)471     template <typename _ReturnType, typename _Function> std::false_type _IsCallable(_Function, ...) { return std::false_type(); }
472 
473     template <>
474     struct _TaskTypeTraits<void>
475     {
476         typedef void _TaskRetType;
477         typedef void _TaskRetType_abi;
478         typedef _TypeSelectorNoAsync _AsyncKind;
479         typedef _Unit_type _NormalizedTaskRetType;
480 
481         static const bool _IsAsyncTask = false;
482         static const bool _IsUnwrappedTaskOrAsync = false;
483     };
484 
485     // ***************************************************************************
486     // Template type traits and helpers for async production APIs:
487     //
488 
489     struct _ZeroArgumentFunctor { };
490     struct _OneArgumentFunctor { };
491     struct _TwoArgumentFunctor { };
492     struct _ThreeArgumentFunctor { };
493 
494     // ****************************************
495     // CLASS TYPES:
496 
497     // mutable functions
498     // ********************
499     // THREE ARGUMENTS:
500 
501     // non-void arg:
502     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
503     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3));
504 
505     // non-void arg:
506     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
507     _Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3));
508 
509     // non-void arg:
510     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
511     _Arg3 _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3));
512 
513     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
514     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3));
515 
516     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
517     _ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3));
518 
519     // ********************
520     // TWO ARGUMENTS:
521 
522     // non-void arg:
523     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
524     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2));
525 
526     // non-void arg:
527     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
528     _Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2));
529 
530     // non-void arg:
531     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
532     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2));
533 
534     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
535     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2));
536 
537     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
538     _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2));
539 
540     // ********************
541     // ONE ARGUMENT:
542 
543     // non-void arg:
544     template<typename _Class, typename _ReturnType, typename _Arg1>
545     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1));
546 
547     // non-void arg:
548     template<typename _Class, typename _ReturnType, typename _Arg1>
549     void _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1));
550 
551     // non-void arg:
552     template<typename _Class, typename _ReturnType, typename _Arg1>
553     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1));
554 
555     template<typename _Class, typename _ReturnType, typename _Arg1>
556     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1));
557 
558     template<typename _Class, typename _ReturnType, typename _Arg1>
559     _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1));
560 
561     // ********************
562     // ZERO ARGUMENT:
563 
564     // void arg:
565     template<typename _Class, typename _ReturnType>
566     void _Arg1ClassHelperThunk(_ReturnType(_Class::*)());
567 
568     // void arg:
569     template<typename _Class, typename _ReturnType>
570     void _Arg2ClassHelperThunk(_ReturnType(_Class::*)());
571 
572     // void arg:
573     template<typename _Class, typename _ReturnType>
574     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)());
575 
576     // void arg:
577     template<typename _Class, typename _ReturnType>
578     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)());
579 
580     template<typename _Class, typename _ReturnType>
581     _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)());
582 
583     // ********************
584     // THREE ARGUMENTS:
585 
586     // non-void arg:
587     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
588     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const);
589 
590     // non-void arg:
591     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
592     _Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const);
593 
594     // non-void arg:
595     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
596     _Arg3 _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const);
597 
598     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
599     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const);
600 
601     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
602     _ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const);
603 
604     // ********************
605     // TWO ARGUMENTS:
606 
607     // non-void arg:
608     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
609     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const);
610 
611     // non-void arg:
612     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
613     _Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const);
614 
615     // non-void arg:
616     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
617     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const);
618 
619     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
620     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const);
621 
622     template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
623     _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2) const);
624 
625     // ********************
626     // ONE ARGUMENT:
627 
628     // non-void arg:
629     template<typename _Class, typename _ReturnType, typename _Arg1>
630     _Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const);
631 
632     // non-void arg:
633     template<typename _Class, typename _ReturnType, typename _Arg1>
634     void _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const);
635 
636     // non-void arg:
637     template<typename _Class, typename _ReturnType, typename _Arg1>
638     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const);
639 
640     template<typename _Class, typename _ReturnType, typename _Arg1>
641     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const);
642 
643     template<typename _Class, typename _ReturnType, typename _Arg1>
644     _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1) const);
645 
646     // ********************
647     // ZERO ARGUMENT:
648 
649     // void arg:
650     template<typename _Class, typename _ReturnType>
651     void _Arg1ClassHelperThunk(_ReturnType(_Class::*)() const);
652 
653     // void arg:
654     template<typename _Class, typename _ReturnType>
655     void _Arg2ClassHelperThunk(_ReturnType(_Class::*)() const);
656 
657     // void arg:
658     template<typename _Class, typename _ReturnType>
659     void _Arg3ClassHelperThunk(_ReturnType(_Class::*)() const);
660 
661     // void arg:
662     template<typename _Class, typename _ReturnType>
663     _ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)() const);
664 
665     template<typename _Class, typename _ReturnType>
666     _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)() const);
667 
668     // ****************************************
669     // POINTER TYPES:
670 
671     // ********************
672     // THREE ARGUMENTS:
673 
674     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
675     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3));
676 
677     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
678     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3));
679 
680     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
681     _Arg3 _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3));
682 
683     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
684     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3));
685 
686     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
687     _ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3));
688 
689     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
690     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3));
691 
692     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
693     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3));
694 
695     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
696     _Arg3 _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3));
697 
698     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
699     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3));
700 
701     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
702     _ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3));
703 
704     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
705     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3));
706 
707     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
708     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3));
709 
710     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
711     _Arg3 _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3));
712 
713     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
714     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3));
715 
716     template<typename _ReturnType, typename _Arg1, typename _Arg2, typename _Arg3>
717     _ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3));
718 
719     // ********************
720     // TWO ARGUMENTS:
721 
722     template<typename _ReturnType, typename _Arg1, typename _Arg2>
723     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
724 
725     template<typename _ReturnType, typename _Arg1, typename _Arg2>
726     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
727 
728     template<typename _ReturnType, typename _Arg1, typename _Arg2>
729     void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
730 
731     template<typename _ReturnType, typename _Arg1, typename _Arg2>
732     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
733 
734     template<typename _ReturnType, typename _Arg1, typename _Arg2>
735     _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2));
736 
737     template<typename _ReturnType, typename _Arg1, typename _Arg2>
738     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
739 
740     template<typename _ReturnType, typename _Arg1, typename _Arg2>
741     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
742 
743     template<typename _ReturnType, typename _Arg1, typename _Arg2>
744     void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
745 
746     template<typename _ReturnType, typename _Arg1, typename _Arg2>
747     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
748 
749     template<typename _ReturnType, typename _Arg1, typename _Arg2>
750     _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2));
751 
752     template<typename _ReturnType, typename _Arg1, typename _Arg2>
753     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
754 
755     template<typename _ReturnType, typename _Arg1, typename _Arg2>
756     _Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
757 
758     template<typename _ReturnType, typename _Arg1, typename _Arg2>
759     void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
760 
761     template<typename _ReturnType, typename _Arg1, typename _Arg2>
762     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
763 
764     template<typename _ReturnType, typename _Arg1, typename _Arg2>
765     _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2));
766 
767     // ********************
768     // ONE ARGUMENT:
769 
770     template<typename _ReturnType, typename _Arg1>
771     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
772 
773     template<typename _ReturnType, typename _Arg1>
774     void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
775 
776     template<typename _ReturnType, typename _Arg1>
777     void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
778 
779     template<typename _ReturnType, typename _Arg1>
780     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
781 
782     template<typename _ReturnType, typename _Arg1>
783     _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1));
784 
785     template<typename _ReturnType, typename _Arg1>
786     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
787 
788     template<typename _ReturnType, typename _Arg1>
789     void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
790 
791     template<typename _ReturnType, typename _Arg1>
792     void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
793 
794     template<typename _ReturnType, typename _Arg1>
795     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
796 
797     template<typename _ReturnType, typename _Arg1>
798     _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1));
799 
800     template<typename _ReturnType, typename _Arg1>
801     _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
802 
803     template<typename _ReturnType, typename _Arg1>
804     void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
805 
806     template<typename _ReturnType, typename _Arg1>
807     void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
808 
809     template<typename _ReturnType, typename _Arg1>
810     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
811 
812     template<typename _ReturnType, typename _Arg1>
813     _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1));
814 
815     // ********************
816     // ZERO ARGUMENT:
817 
818     template<typename _ReturnType>
819     void _Arg1PFNHelperThunk(_ReturnType(__cdecl *)());
820 
821     template<typename _ReturnType>
822     void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)());
823 
824     template<typename _ReturnType>
825     void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)());
826 
827     template<typename _ReturnType>
828     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)());
829 
830     template<typename _ReturnType>
831     _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)());
832 
833     template<typename _ReturnType>
834     void _Arg1PFNHelperThunk(_ReturnType(__stdcall *)());
835 
836     template<typename _ReturnType>
837     void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)());
838 
839     template<typename _ReturnType>
840     void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)());
841 
842     template<typename _ReturnType>
843     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)());
844 
845     template<typename _ReturnType>
846     _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)());
847 
848     template<typename _ReturnType>
849     void _Arg1PFNHelperThunk(_ReturnType(__fastcall *)());
850 
851     template<typename _ReturnType>
852     void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)());
853 
854     template<typename _ReturnType>
855     void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)());
856 
857     template<typename _ReturnType>
858     _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)());
859 
860     template<typename _ReturnType>
861     _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)());
862 
863     template<typename _T>
864     struct _FunctorArguments
865     {
866         static const size_t _Count = 0;
867     };
868 
869     template<>
870     struct _FunctorArguments<_OneArgumentFunctor>
871     {
872         static const size_t _Count = 1;
873     };
874 
875     template<>
876     struct _FunctorArguments<_TwoArgumentFunctor>
877     {
878         static const size_t _Count = 2;
879     };
880 
881     template<>
882     struct _FunctorArguments<_ThreeArgumentFunctor>
883     {
884         static const size_t _Count = 3;
885     };
886 
887     template<typename _T>
888     struct _FunctorTypeTraits
889     {
890         typedef decltype(_ArgumentCountHelper(&(_T::operator()))) _ArgumentCountType;
891         static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
892 
893         typedef decltype(_ReturnTypeClassHelperThunk(&(_T::operator()))) _ReturnType;
894         typedef decltype(_Arg1ClassHelperThunk(&(_T::operator()))) _Argument1Type;
895         typedef decltype(_Arg2ClassHelperThunk(&(_T::operator()))) _Argument2Type;
896         typedef decltype(_Arg3ClassHelperThunk(&(_T::operator()))) _Argument3Type;
897     };
898 
899     template<typename _T>
900     struct _FunctorTypeTraits<_T *>
901     {
902         typedef decltype(_ArgumentCountHelper(stdx::declval<_T*>())) _ArgumentCountType;
903         static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
904 
905         typedef decltype(_ReturnTypePFNHelperThunk(stdx::declval<_T*>())) _ReturnType;
906         typedef decltype(_Arg1PFNHelperThunk(stdx::declval<_T*>())) _Argument1Type;
907         typedef decltype(_Arg2PFNHelperThunk(stdx::declval<_T*>())) _Argument2Type;
908         typedef decltype(_Arg3PFNHelperThunk(stdx::declval<_T*>())) _Argument3Type;
909     };
910 
911     task<void> _To_task();
912 
913     template <typename _Function> auto _IsVoidConversionHelper(_Function _Func, int) -> typename decltype(_Func(_To_task()), std::true_type());
914     template <typename _Function> std::false_type _IsVoidConversionHelper(_Function _Func, ...);
915 
916     template <typename T> std::true_type _VoidIsTaskHelper(task<T> _Arg, int);
917     template <typename T> std::false_type _VoidIsTaskHelper(T _Arg, ...);
918 
919     template<typename _Function, typename _ExpectedParameterType, const bool _IsVoidConversion = std::is_same<decltype(_IsVoidConversionHelper(stdx::declval<_Function>(), 0)), std::true_type>::value, const size_t _Count = _FunctorTypeTraits<_Function>::_ArgumentCount>
920     struct _FunctionTypeTraits
921     {
922         typedef typename _Unhat<typename _FunctorTypeTraits<_Function>::_Argument2Type>::_Value _FuncRetType;
923         static_assert(std::is_same<typename _FunctorTypeTraits<_Function>::_Argument1Type, _ExpectedParameterType>::value ||
924                     std::is_same<typename _FunctorTypeTraits<_Function>::_Argument1Type, task<_ExpectedParameterType>>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)");
925 
926         typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task;
927     };
928 
929     //if there is a continuation parameter, then must use void/no return value
930     template<typename _Function, typename _ExpectedParameterType, const bool _IsVoidConversion>
931     struct _FunctionTypeTraits<_Function, _ExpectedParameterType, _IsVoidConversion, 1>
932     {
933         typedef void _FuncRetType;
934         static_assert(std::is_same<typename _FunctorTypeTraits<_Function>::_Argument1Type, _ExpectedParameterType>::value ||
935                     std::is_same<typename _FunctorTypeTraits<_Function>::_Argument1Type, task<_ExpectedParameterType>>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)");
936 
937         typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task;
938     };
939 
940     template<typename _Function>
941     struct _FunctionTypeTraits<_Function, void, true, 1>
942     {
943         typedef void _FuncRetType;
944         static_assert(std::is_same<typename _FunctorTypeTraits<_Function>::_Argument1Type, decltype(_To_task())>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)");
945 
946         typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task;
947     };
948 
949     template<typename _Function>
950     struct _FunctionTypeTraits<_Function, void, false, 1>
951     {
952         typedef typename _Unhat<typename _FunctorTypeTraits<_Function>::_Argument1Type>::_Value _FuncRetType;
953 
954         typedef std::false_type _Takes_task;
955     };
956 
957     template<typename _Function, typename _ExpectedParameterType, const bool _IsVoidConversion>
958     struct _FunctionTypeTraits<_Function, _ExpectedParameterType, _IsVoidConversion, 0>
959     {
960         typedef void _FuncRetType;
961 
962         typedef std::false_type _Takes_task;
963     };
964 
965     template<typename _Function, typename _ReturnType>
966     struct _ContinuationTypeTraits
967     {
968         typedef typename task<typename _TaskTypeTraits<typename _FunctionTypeTraits<_Function, _ReturnType>::_FuncRetType>::_TaskRetType_abi> _TaskOfType;
969     };
970 
971     // _InitFunctorTypeTraits is used to decide whether a task constructed with a lambda should be unwrapped. Depending on how the variable is
972     // declared, the constructor may or may not perform unwrapping. For eg.
973     //
974     //  This declaration SHOULD NOT cause unwrapping
975     //    task<task<void>> t1([]() -> task<void> {
976     //        task<void> t2([]() {});
977     //        return t2;
978     //    });
979     //
980     // This declaration SHOULD cause unwrapping
981     //    task<void>> t1([]() -> task<void> {
982     //        task<void> t2([]() {});
983     //        return t2;
984     //    });
985     // If the type of the task is the same as the return type of the function, no unwrapping should take place. Else normal rules apply.
986     template <typename _TaskType, typename _FuncRetType>
987     struct _InitFunctorTypeTraits
988     {
989         typedef typename _TaskTypeTraits<_FuncRetType>::_AsyncKind _AsyncKind;
990         static const bool _IsAsyncTask = _TaskTypeTraits<_FuncRetType>::_IsAsyncTask;
991         static const bool _IsUnwrappedTaskOrAsync = _TaskTypeTraits<_FuncRetType>::_IsUnwrappedTaskOrAsync;
992     };
993 
994     template<typename T>
995     struct _InitFunctorTypeTraits<T, T>
996     {
997         typedef _TypeSelectorNoAsync _AsyncKind;
998         static const bool _IsAsyncTask = false;
999         static const bool _IsUnwrappedTaskOrAsync = false;
1000     };
1001     /// <summary>
1002     ///     Helper object used for LWT invocation.
1003     /// </summary>
1004     struct _TaskProcThunk
1005     {
_TaskProcThunkConcurrency_winrt::details::_TaskProcThunk1006         _TaskProcThunk(const std::function<HRESULT(void)> & _Callback) :
1007         _M_func(_Callback)
1008         {
1009         }
1010 
_BridgeConcurrency_winrt::details::_TaskProcThunk1011         static void __cdecl _Bridge(void *_PData)
1012         {
1013             _TaskProcThunk *_PThunk = reinterpret_cast<_TaskProcThunk *>(_PData);
1014 #if _MSC_VER >= 1800
1015             _Holder _ThunkHolder(_PThunk);
1016 #endif
1017             _PThunk->_M_func();
1018 #if _MSC_VER < 1800
1019             delete _PThunk;
1020 #endif
1021         }
1022     private:
1023 #if _MSC_VER >= 1800
1024         // RAII holder
1025         struct _Holder
1026         {
_HolderConcurrency_winrt::details::_TaskProcThunk::_Holder1027             _Holder(_TaskProcThunk * _PThunk) : _M_pThunk(_PThunk)
1028             {
1029             }
1030 
~_HolderConcurrency_winrt::details::_TaskProcThunk::_Holder1031             ~_Holder()
1032             {
1033                 delete _M_pThunk;
1034             }
1035 
1036             _TaskProcThunk * _M_pThunk;
1037 
1038         private:
1039             _Holder& operator=(const _Holder&);
1040         };
1041 #endif
1042         std::function<HRESULT(void)> _M_func;
1043         _TaskProcThunk& operator=(const _TaskProcThunk&);
1044     };
1045 
1046     /// <summary>
1047     ///     Schedule a functor with automatic inlining. Note that this is "fire and forget" scheduling, which cannot be
1048     ///     waited on or canceled after scheduling.
1049     ///     This schedule method will perform automatic inlining base on <paramref value="_InliningMode"/>.
1050     /// </summary>
1051     /// <param name="_Func">
1052     ///     The user functor need to be scheduled.
1053     /// </param>
1054     /// <param name="_InliningMode">
1055     ///     The inlining scheduling policy for current functor.
1056     /// </param>
1057 #if _MSC_VER >= 1800
1058     typedef Concurrency::details::_TaskInliningMode_t _TaskInliningMode;
1059 #else
1060     typedef Concurrency::details::_TaskInliningMode _TaskInliningMode;
1061 #endif
_ScheduleFuncWithAutoInline(const std::function<HRESULT (void)> & _Func,_TaskInliningMode _InliningMode)1062     static void _ScheduleFuncWithAutoInline(const std::function<HRESULT(void)> & _Func, _TaskInliningMode _InliningMode)
1063     {
1064 #if _MSC_VER >= 1800
1065         Concurrency::details::_TaskCollection_t::_RunTask(&_TaskProcThunk::_Bridge, new _TaskProcThunk(_Func), _InliningMode);
1066 #else
1067         Concurrency::details::_StackGuard _Guard;
1068         if (_Guard._ShouldInline(_InliningMode))
1069         {
1070             _Func();
1071         }
1072         else
1073         {
1074             Concurrency::details::_CurrentScheduler::_ScheduleTask(reinterpret_cast<Concurrency::TaskProc>(&_TaskProcThunk::_Bridge), new _TaskProcThunk(_Func));
1075         }
1076 #endif
1077     }
1078     class _ContextCallback
1079     {
1080         typedef std::function<HRESULT(void)> _CallbackFunction;
1081 
1082     public:
1083 
_CaptureCurrent()1084         static _ContextCallback _CaptureCurrent()
1085         {
1086             _ContextCallback _Context;
1087             _Context._Capture();
1088             return _Context;
1089         }
1090 
~_ContextCallback()1091         ~_ContextCallback()
1092         {
1093             _Reset();
1094         }
1095 
_ContextCallback(bool _DeferCapture=false)1096         _ContextCallback(bool _DeferCapture = false)
1097         {
1098             if (_DeferCapture)
1099             {
1100                 _M_context._M_captureMethod = _S_captureDeferred;
1101             }
1102             else
1103             {
1104                 _M_context._M_pContextCallback = nullptr;
1105             }
1106         }
1107 
1108         // Resolves a context that was created as _S_captureDeferred based on the environment (ancestor, current context).
_Resolve(bool _CaptureCurrent)1109         void _Resolve(bool _CaptureCurrent)
1110         {
1111             if (_M_context._M_captureMethod == _S_captureDeferred)
1112             {
1113                 _M_context._M_pContextCallback = nullptr;
1114 
1115                 if (_CaptureCurrent)
1116                 {
1117                     if (_IsCurrentOriginSTA())
1118                     {
1119                         _Capture();
1120                     }
1121 #if _UITHREADCTXT_SUPPORT
1122                     else
1123                     {
1124                         // This method will fail if not called from the UI thread.
1125                         HRESULT _Hr = CaptureUiThreadContext(&_M_context._M_pContextCallback);
1126                         if (FAILED(_Hr))
1127                         {
1128                             _M_context._M_pContextCallback = nullptr;
1129                         }
1130                     }
1131 #endif // _UITHREADCTXT_SUPPORT
1132                 }
1133             }
1134         }
1135 
_Capture()1136         void _Capture()
1137         {
1138             HRESULT _Hr = CoGetObjectContext(IID_IContextCallback, reinterpret_cast<void **>(&_M_context._M_pContextCallback));
1139             if (FAILED(_Hr))
1140             {
1141                 _M_context._M_pContextCallback = nullptr;
1142             }
1143         }
1144 
_ContextCallback(const _ContextCallback & _Src)1145         _ContextCallback(const _ContextCallback& _Src)
1146         {
1147             _Assign(_Src._M_context._M_pContextCallback);
1148         }
1149 
_ContextCallback(_ContextCallback && _Src)1150         _ContextCallback(_ContextCallback&& _Src)
1151         {
1152             _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
1153             _Src._M_context._M_pContextCallback = nullptr;
1154         }
1155 
operator =(const _ContextCallback & _Src)1156         _ContextCallback& operator=(const _ContextCallback& _Src)
1157         {
1158             if (this != &_Src)
1159             {
1160                 _Reset();
1161                 _Assign(_Src._M_context._M_pContextCallback);
1162             }
1163             return *this;
1164         }
1165 
operator =(_ContextCallback && _Src)1166         _ContextCallback& operator=(_ContextCallback&& _Src)
1167         {
1168             if (this != &_Src)
1169             {
1170                 _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
1171                 _Src._M_context._M_pContextCallback = nullptr;
1172             }
1173             return *this;
1174         }
1175 
_HasCapturedContext() const1176         bool _HasCapturedContext() const
1177         {
1178             _CONCRT_ASSERT(_M_context._M_captureMethod != _S_captureDeferred);
1179             return (_M_context._M_pContextCallback != nullptr);
1180         }
1181 
_CallInContext(_CallbackFunction _Func) const1182         HRESULT _CallInContext(_CallbackFunction _Func) const
1183         {
1184             if (!_HasCapturedContext())
1185             {
1186                 _Func();
1187             }
1188             else
1189             {
1190                 ComCallData callData;
1191                 ZeroMemory(&callData, sizeof(callData));
1192                 callData.pUserDefined = reinterpret_cast<void *>(&_Func);
1193 
1194                 HRESULT _Hr = _M_context._M_pContextCallback->ContextCallback(&_Bridge, &callData, IID_ICallbackWithNoReentrancyToApplicationSTA, 5, nullptr);
1195                 if (FAILED(_Hr))
1196                 {
1197                     return _Hr;
1198                 }
1199             }
1200             return S_OK;
1201         }
1202 
operator ==(const _ContextCallback & _Rhs) const1203         bool operator==(const _ContextCallback& _Rhs) const
1204         {
1205             return (_M_context._M_pContextCallback == _Rhs._M_context._M_pContextCallback);
1206         }
1207 
operator !=(const _ContextCallback & _Rhs) const1208         bool operator!=(const _ContextCallback& _Rhs) const
1209         {
1210             return !(operator==(_Rhs));
1211         }
1212 
1213     private:
1214 
_Reset()1215         void _Reset()
1216         {
1217             if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
1218             {
1219                 _M_context._M_pContextCallback->Release();
1220             }
1221         }
1222 
_Assign(IContextCallback * _PContextCallback)1223         void _Assign(IContextCallback *_PContextCallback)
1224         {
1225             _M_context._M_pContextCallback = _PContextCallback;
1226             if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
1227             {
1228                 _M_context._M_pContextCallback->AddRef();
1229             }
1230         }
1231 
_Bridge(ComCallData * _PParam)1232         static HRESULT __stdcall _Bridge(ComCallData *_PParam)
1233         {
1234             _CallbackFunction *pFunc = reinterpret_cast<_CallbackFunction *>(_PParam->pUserDefined);
1235             return (*pFunc)();
1236         }
1237 
1238         // Returns the origin information for the caller (runtime / Windows Runtime apartment as far as task continuations need know)
_IsCurrentOriginSTA()1239         static bool _IsCurrentOriginSTA()
1240         {
1241             APTTYPE _AptType;
1242             APTTYPEQUALIFIER _AptTypeQualifier;
1243 
1244             HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
1245             if (SUCCEEDED(hr))
1246             {
1247                 // We determine the origin of a task continuation by looking at where .then is called, so we can tell whether
1248                 // to need to marshal the continuation back to the originating apartment. If an STA thread is in executing in
1249                 // a neutral aparment when it schedules a continuation, we will not marshal continuations back to the STA,
1250                 // since variables used within a neutral apartment are expected to be apartment neutral.
1251                 switch (_AptType)
1252                 {
1253                 case APTTYPE_MAINSTA:
1254                 case APTTYPE_STA:
1255                     return true;
1256                 default:
1257                     break;
1258                 }
1259             }
1260             return false;
1261         }
1262 
1263         union
1264         {
1265             IContextCallback *_M_pContextCallback;
1266             size_t _M_captureMethod;
1267         } _M_context;
1268 
1269         static const size_t _S_captureDeferred = 1;
1270     };
1271 
1272 #if _MSC_VER >= 1800
1273     template<typename _Type>
1274     struct _ResultHolder
1275     {
SetConcurrency_winrt::details::_ResultHolder1276         void Set(const _Type& _type)
1277         {
1278             _Result = _type;
1279         }
1280 
GetConcurrency_winrt::details::_ResultHolder1281         _Type Get()
1282         {
1283             return _Result;
1284         }
1285 
1286         _Type _Result;
1287     };
1288 
1289     template<typename _Type>
1290     struct _ResultHolder<_Type*>
1291     {
SetConcurrency_winrt::details::_ResultHolder1292         void Set(_Type* const & _type)
1293         {
1294             _M_Result = _type;
1295         }
1296 
GetConcurrency_winrt::details::_ResultHolder1297         _Type* Get()
1298         {
1299             return _M_Result.Get();
1300         }
1301     private:
1302         // ::Platform::Agile handle specialization of all hats
1303         // including ::Platform::String and ::Platform::Array
1304         Agile<_Type*> _M_Result;
1305     };
1306 
1307     //
1308     // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs.
1309     //
1310     template<typename _Type>
1311     struct _ResultHolder<std::vector<_Type*>>
1312     {
SetConcurrency_winrt::details::_ResultHolder1313         void Set(const std::vector<_Type*>& _type)
1314         {
1315             _Result.reserve(_type.size());
1316 
1317             for (auto _PTask = _type.begin(); _PTask != _type.end(); ++_PTask)
1318             {
1319                 _Result.emplace_back(*_PTask);
1320             }
1321         }
1322 
GetConcurrency_winrt::details::_ResultHolder1323         std::vector<_Type*> Get()
1324         {
1325             // Return vectory<T^> with the objects that are marshaled in the proper appartment
1326             std::vector<_Type*> _Return;
1327             _Return.reserve(_Result.size());
1328 
1329             for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask)
1330             {
1331                 _Return.push_back(_PTask->Get()); // Agile will marshal the object to appropriate appartment if neccessary
1332             }
1333 
1334             return _Return;
1335         }
1336 
1337         std::vector< Agile<_Type*> > _Result;
1338     };
1339 
1340     template<typename _Type>
1341     struct _ResultHolder<std::pair<_Type*, void*> >
1342     {
SetConcurrency_winrt::details::_ResultHolder1343         void Set(const std::pair<_Type*, size_t>& _type)
1344         {
1345             _M_Result = _type;
1346         }
1347 
GetConcurrency_winrt::details::_ResultHolder1348         std::pair<_Type*, size_t> Get()
1349         {
1350             return std::make_pair(_M_Result.first, _M_Result.second);
1351         }
1352     private:
1353         std::pair<Agile<_Type*>, size_t> _M_Result;
1354     };
1355 #else
1356     template<typename _Type>
1357     struct _ResultContext
1358     {
_GetContextConcurrency_winrt::details::_ResultContext1359         static _ContextCallback _GetContext(bool /* _RuntimeAggregate */)
1360         {
1361             return _ContextCallback();
1362         }
1363 
_GetValueConcurrency_winrt::details::_ResultContext1364         static _Type _GetValue(_Type _ObjInCtx, const _ContextCallback & /* _Ctx */, bool /* _RuntimeAggregate */)
1365         {
1366             return _ObjInCtx;
1367         }
1368     };
1369 
1370     template<typename _Type, size_t N = 0, bool bIsArray = std::is_array<_Type>::value>
1371     struct _MarshalHelper
1372     {
1373     };
1374     template<typename _Type, size_t N>
1375     struct _MarshalHelper<_Type, N, true>
1376     {
_PerformConcurrency_winrt::details::_MarshalHelper1377         static _Type* _Perform(_Type(&_ObjInCtx)[N], const _ContextCallback& _Ctx)
1378         {
1379             static_assert(__is_valid_winrt_type(_Type*), "must be a WinRT array compatible type");
1380             if (_ObjInCtx == nullptr)
1381             {
1382                 return nullptr;
1383             }
1384 
1385             HRESULT _Hr;
1386             IStream * _PStream;
1387             _Ctx._CallInContext([&]() -> HRESULT {
1388                 // It isn't safe to simply reinterpret_cast a hat type to IUnknown* because some types do not have a real vtable ptr.
1389                 // Instead, we could to create a property value to make it "grow" the vtable ptr but instead primitives are not marshalled.
1390 
1391                 IUnknown * _PUnk = winrt_array_type::create(_ObjInCtx, N);
1392                 _Hr = CoMarshalInterThreadInterfaceInStream(winrt_type<_Type>::getuuid(), _PUnk, &_PStream);
1393                 return S_OK;
1394             });
1395 
1396             // With an APPX manifest, this call should never fail.
1397             _CONCRT_ASSERT(SUCCEEDED(_Hr));
1398 
1399             _Type* _Proxy;
1400             //
1401             // Cannot use IID_PPV_ARGS with ^ types.
1402             //
1403             _Hr = CoGetInterfaceAndReleaseStream(_PStream, winrt_type<_Type>::getuuid(), reinterpret_cast<void**>(&_Proxy));
1404             if (FAILED(_Hr))
1405             {
1406                 throw std::make_exception_ptr(_Hr);
1407             }
1408             return _Proxy;
1409         }
1410     };
1411     template<typename _Type>
1412     struct _MarshalHelper<_Type, 0, false>
1413     {
_PerformConcurrency_winrt::details::_MarshalHelper1414         static _Type* _Perform(_Type* _ObjInCtx, const _ContextCallback& _Ctx)
1415         {
1416             static_assert(std::is_base_of<IUnknown, _Type>::value || __is_valid_winrt_type(_Type), "must be a COM or WinRT type");
1417             if (_ObjInCtx == nullptr)
1418             {
1419                 return nullptr;
1420             }
1421 
1422             HRESULT _Hr;
1423             IStream * _PStream;
1424             _Ctx._CallInContext([&]() -> HRESULT {
1425                 // It isn't safe to simply reinterpret_cast a hat type to IUnknown* because some types do not have a real vtable ptr.
1426                 // Instead, we could to create a property value to make it "grow" the vtable ptr but instead primitives are not marshalled.
1427 
1428                 IUnknown * _PUnk = winrt_type<_Type>::create(_ObjInCtx);
1429                 _Hr = CoMarshalInterThreadInterfaceInStream(winrt_type<_Type>::getuuid(), _PUnk, &_PStream);
1430                 return S_OK;
1431             });
1432 
1433             // With an APPX manifest, this call should never fail.
1434             _CONCRT_ASSERT(SUCCEEDED(_Hr));
1435 
1436             _Type* _Proxy;
1437             //
1438             // Cannot use IID_PPV_ARGS with ^ types.
1439             //
1440             _Hr = CoGetInterfaceAndReleaseStream(_PStream, winrt_type<_Type>::getuuid(), reinterpret_cast<void**>(&_Proxy));
1441             if (FAILED(_Hr))
1442             {
1443                 throw std::make_exception_ptr(_Hr);
1444             }
1445             return _Proxy;
1446         }
1447     };
1448 
1449     // Arrays must be converted to IPropertyValue objects.
1450 
1451     template<>
1452     struct _MarshalHelper<HSTRING__>
1453     {
_PerformConcurrency_winrt::details::_MarshalHelper1454         static HSTRING _Perform(HSTRING _ObjInCtx, const _ContextCallback& _Ctx)
1455         {
1456             return _ObjInCtx;
1457         }
1458     };
1459 
1460     template<typename _Type>
_Marshal(_Type * _ObjInCtx,const _ContextCallback & _Ctx)1461     _Type* _Marshal(_Type* _ObjInCtx, const _ContextCallback& _Ctx)
1462     {
1463         return _MarshalHelper<_Type>::_Perform(_ObjInCtx, _Ctx);
1464     }
1465 
1466     template<typename _Type>
1467     struct _InContext
1468     {
_GetConcurrency_winrt::details::_InContext1469         static _Type _Get(_Type _ObjInCtx, const _ContextCallback& _Ctx)
1470         {
1471             return _ObjInCtx;
1472         }
1473     };
1474 
1475     template<typename _Type>
1476     struct _InContext<_Type*>
1477     {
_GetConcurrency_winrt::details::_InContext1478         static _Type* _Get(_Type* _ObjInCtx, const _ContextCallback& _Ctx)
1479         {
1480             _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent();
1481             if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext)
1482             {
1483                 return _ObjInCtx;
1484             }
1485 
1486             //
1487             // The object is from another apartment. If it's marshalable, do so.
1488             //
1489             return _Marshal<_Type>(_ObjInCtx, _Ctx);
1490         }
1491     };
1492 
1493     template<typename _Type>
1494     struct _ResultContext<_Type*>
1495     {
_GetValueConcurrency_winrt::details::_ResultContext1496         static _Type* _GetValue(_Type* _ObjInCtx, const _ContextCallback& _Ctx, bool /* _RuntimeAggregate */)
1497         {
1498             return _InContext<_Type*>::_Get(_ObjInCtx, _Ctx);
1499         }
1500 
_GetContextConcurrency_winrt::details::_ResultContext1501         static _ContextCallback _GetContext(bool /* _RuntimeAggregate */)
1502         {
1503             return _ContextCallback::_CaptureCurrent();
1504         }
1505     };
1506 
1507     //
1508     // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs.
1509     //
1510     template<typename _Type>
1511     struct _ResultContext<std::vector<_Type*>>
1512     {
_GetValueConcurrency_winrt::details::_ResultContext1513         static std::vector<_Type*> _GetValue(std::vector<_Type*> _ObjInCtx, const _ContextCallback& _Ctx, bool _RuntimeAggregate)
1514         {
1515             if (!_RuntimeAggregate)
1516             {
1517                 return _ObjInCtx;
1518             }
1519 
1520             _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent();
1521             if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext)
1522             {
1523                 return _ObjInCtx;
1524             }
1525 
1526             for (auto _It = _ObjInCtx.begin(); _It != _ObjInCtx.end(); ++_It)
1527             {
1528                 *_It = _Marshal<_Type>(*_It, _Ctx);
1529             }
1530 
1531             return _ObjInCtx;
1532         }
1533 
_GetContextConcurrency_winrt::details::_ResultContext1534         static _ContextCallback _GetContext(bool _RuntimeAggregate)
1535         {
1536             if (!_RuntimeAggregate)
1537             {
1538                 return _ContextCallback();
1539             }
1540             else
1541             {
1542                 return _ContextCallback::_CaptureCurrent();
1543             }
1544         }
1545     };
1546 
1547     template<typename _Type>
1548     struct _ResultContext<std::pair<_Type*, size_t>>
1549     {
_GetValueConcurrency_winrt::details::_ResultContext1550         static std::pair<_Type*, size_t> _GetValue(std::pair<_Type*, size_t> _ObjInCtx, const _ContextCallback& _Ctx, bool _RuntimeAggregate)
1551         {
1552             if (!_RuntimeAggregate)
1553             {
1554                 return _ObjInCtx;
1555             }
1556 
1557             _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent();
1558             if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext)
1559             {
1560                 return _ObjInCtx;
1561             }
1562 
1563             return std::pair<_Type*, size_t>(_Marshal<_Type>(_ObjInCtx.first, _Ctx), _ObjInCtx.second);
1564         }
1565 
_GetContextConcurrency_winrt::details::_ResultContext1566         static _ContextCallback _GetContext(bool _RuntimeAggregate)
1567         {
1568             if (!_RuntimeAggregate)
1569             {
1570                 return _ContextCallback();
1571             }
1572             else
1573             {
1574                 return _ContextCallback::_CaptureCurrent();
1575             }
1576         }
1577     };
1578 #endif
1579     // An exception thrown by the task body is captured in an exception holder and it is shared with all value based continuations rooted at the task.
1580     // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
1581     // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
1582     struct _ExceptionHolder
1583     {
1584 #if _MSC_VER >= 1800
1585     private:
ReportUnhandledErrorConcurrency_winrt::details::_ExceptionHolder1586         void ReportUnhandledError()
1587         {
1588             if (_M_winRTException != nullptr)
1589             {
1590                 throw _M_winRTException.Get();
1591             }
1592         }
1593     public:
_ExceptionHolderConcurrency_winrt::details::_ExceptionHolder1594         explicit _ExceptionHolder(const std::exception_ptr& _E, const _TaskCreationCallstack &_stackTrace) :
1595             _M_exceptionObserved(0), _M_stdException(_E), _M_stackTrace(_stackTrace)
1596         {
1597         }
1598 
_ExceptionHolderConcurrency_winrt::details::_ExceptionHolder1599         explicit _ExceptionHolder(IRestrictedErrorInfo*& _E, const _TaskCreationCallstack &_stackTrace) :
1600             _M_exceptionObserved(0), _M_winRTException(_E), _M_stackTrace(_stackTrace)
1601         {
1602         }
1603 #else
1604         explicit _ExceptionHolder(const std::exception_ptr& _E, void* _SourceAddressHint) :
1605         _M_exceptionObserved(0), _M_stdException(_E), _M_disassembleMe(_SourceAddressHint)
1606         {
1607         }
1608 
1609         explicit _ExceptionHolder(IRestrictedErrorInfo*& _E, void* _SourceAddressHint) :
1610             _M_exceptionObserved(0), _M_disassembleMe(_SourceAddressHint), _M_winRTException(_E)
1611         {
1612         }
1613 #endif
1614         __declspec(noinline)
~_ExceptionHolderConcurrency_winrt::details::_ExceptionHolder1615             ~_ExceptionHolder()
1616         {
1617             if (_M_exceptionObserved == 0)
1618             {
1619 #if _MSC_VER >= 1800
1620                 // If you are trapped here, it means an exception thrown in task chain didn't get handled.
1621                 // Please add task-based continuation to handle all exceptions coming from tasks.
1622                 // this->_M_stackTrace keeps the creation callstack of the task generates this exception.
1623                 _REPORT_PPLTASK_UNOBSERVED_EXCEPTION();
1624 #else
1625                 // Disassemble at this->_M_disassembleMe to get to the source location right after either the creation of the task (constructor
1626                 // or then method) that encountered this exception, or the set_exception call for a task_completion_event.
1627                 Concurrency::details::_ReportUnobservedException();
1628 #endif
1629             }
1630         }
1631 
_RethrowUserExceptionConcurrency_winrt::details::_ExceptionHolder1632         void _RethrowUserException()
1633         {
1634             if (_M_exceptionObserved == 0)
1635             {
1636 #if _MSC_VER >= 1800
1637                 Concurrency::details::atomic_exchange(_M_exceptionObserved, 1l);
1638 #else
1639                 _InterlockedExchange(&_M_exceptionObserved, 1);
1640 #endif
1641             }
1642 
1643             if (_M_winRTException != nullptr)
1644             {
1645                 throw _M_winRTException.Get();
1646             }
1647             std::rethrow_exception(_M_stdException);
1648         }
1649 
1650         // A variable that remembers if this exception was every rethrown into user code (and hence handled by the user). Exceptions that
1651         // are unobserved when the exception holder is destructed will terminate the process.
1652 #if _MSC_VER >= 1800
1653         Concurrency::details::atomic_long _M_exceptionObserved;
1654 #else
1655         long volatile _M_exceptionObserved;
1656 #endif
1657 
1658         // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered.
1659         std::exception_ptr _M_stdException;
1660         Microsoft::WRL::ComPtr<IRestrictedErrorInfo> _M_winRTException;
1661 
1662         // Disassembling this value will point to a source instruction right after a call instruction. If the call is to create_task,
1663         // a task constructor or the then method, the task created by that method is the one that encountered this exception. If the call
1664         // is to task_completion_event::set_exception, the set_exception method was the source of the exception.
1665         // DO NOT REMOVE THIS VARIABLE. It is extremely helpful for debugging.
1666 #if _MSC_VER >= 1800
1667         _TaskCreationCallstack _M_stackTrace;
1668 #else
1669         void* _M_disassembleMe;
1670 #endif
1671     };
1672 
1673 #ifndef RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoImpl_DEFINED
1674 #define RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoImpl_DEFINED
1675     extern const __declspec(selectany) WCHAR RuntimeClass_Concurrency_winrt_details__AsyncInfoImpl[] = L"Concurrency_winrt.details._AsyncInfoImpl";
1676 #endif
1677 
1678     /// <summary>
1679     ///     Base converter class for converting asynchronous interfaces to IAsyncOperation
1680     /// </summary>
1681     template<typename _AsyncOperationType, typename _CompletionHandlerType, typename _Result_abi>
1682     struct _AsyncInfoImpl abstract : public Microsoft::WRL::RuntimeClass<
1683         Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRt>,
1684         Microsoft::WRL::Implements<Microsoft::WRL::AsyncBase<_CompletionHandlerType>>>
1685     {
1686         InspectableClass(RuntimeClass_Concurrency_winrt_details__AsyncInfoImpl, BaseTrust)
1687     public:
1688         // The async action, action with progress or operation with progress that this stub forwards to.
1689 #if _MSC_VER >= 1800
1690         Agile<_AsyncOperationType> _M_asyncInfo;
1691 #else
1692         Microsoft::WRL::ComPtr<_AsyncOperationType> _M_asyncInfo;
1693         // The context in which this async info is valid - may be different from the context where the completion handler runs,
1694         // and may require marshalling before it is used.
1695         _ContextCallback _M_asyncInfoContext;
1696 #endif
1697 
1698         Microsoft::WRL::ComPtr<_CompletionHandlerType> _M_CompletedHandler;
1699 
_AsyncInfoImplConcurrency_winrt::details::abstract1700         _AsyncInfoImpl(_AsyncOperationType* _AsyncInfo) : _M_asyncInfo(_AsyncInfo)
1701 #if _MSC_VER < 1800
1702             , _M_asyncInfoContext(_ContextCallback::_CaptureCurrent())
1703 #endif
1704         {}
1705 
1706     public:
OnStartConcurrency_winrt::details::abstract1707         virtual HRESULT OnStart() { return S_OK; }
OnCancelConcurrency_winrt::details::abstract1708         virtual void OnCancel() {
1709             Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
1710             HRESULT hr;
1711 #if _MSC_VER >= 1800
1712             if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())))
1713 #else
1714             if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo)))
1715 #endif
1716                 pAsyncInfo->Cancel();
1717             else
1718                 throw std::make_exception_ptr(hr);
1719         }
OnCloseConcurrency_winrt::details::abstract1720         virtual void OnClose() {
1721             Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
1722             HRESULT hr;
1723 #if _MSC_VER >= 1800
1724             if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())))
1725 #else
1726             if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo)))
1727 #endif
1728                 pAsyncInfo->Close();
1729             else
1730                 throw std::make_exception_ptr(hr);
1731         }
1732 
get_ErrorCodeConcurrency_winrt::details::abstract1733         virtual STDMETHODIMP get_ErrorCode(HRESULT* errorCode)
1734         {
1735             Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
1736             HRESULT hr;
1737 #if _MSC_VER >= 1800
1738             if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())))
1739 #else
1740             if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo)))
1741 #endif
1742                 return pAsyncInfo->get_ErrorCode(errorCode);
1743             return hr;
1744         }
1745 
get_IdConcurrency_winrt::details::abstract1746         virtual STDMETHODIMP get_Id(UINT* id)
1747         {
1748             Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
1749             HRESULT hr;
1750 #if _MSC_VER >= 1800
1751             if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())))
1752 #else
1753             if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo)))
1754 #endif
1755                 return pAsyncInfo->get_Id(id);
1756             return hr;
1757         }
1758 
get_StatusConcurrency_winrt::details::abstract1759         virtual STDMETHODIMP get_Status(ABI::Windows::Foundation::AsyncStatus *status)
1760         {
1761             Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
1762             HRESULT hr;
1763 #if _MSC_VER >= 1800
1764             if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())))
1765 #else
1766             if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo)))
1767 #endif
1768                 return pAsyncInfo->get_Status(status);
1769             return hr;
1770         }
1771 
GetResultsConcurrency_winrt::details::abstract1772         virtual STDMETHODIMP GetResults(_Result_abi*) { throw std::runtime_error("derived class must implement"); }
1773 
get_CompletedConcurrency_winrt::details::abstract1774         virtual STDMETHODIMP get_Completed(_CompletionHandlerType** handler)
1775         {
1776             if (!handler) return E_POINTER;
1777             _M_CompletedHandler.CopyTo(handler);
1778             return S_OK;
1779         }
1780 
put_CompletedConcurrency_winrt::details::abstract1781         virtual    STDMETHODIMP put_Completed(_CompletionHandlerType* value)
1782         {
1783             _M_CompletedHandler = value;
1784             Microsoft::WRL::ComPtr<_CompletionHandlerType> handler = Microsoft::WRL::Callback<_CompletionHandlerType>([&](_AsyncOperationType*, ABI::Windows::Foundation::AsyncStatus status) -> HRESULT {
1785 #if _MSC_VER < 1800
1786                 // Update the saved _M_asyncInfo with a proxy valid in the current context if required. Some Windows APIs return an IAsyncInfo
1787                 // that is only valid for the thread that called the API to retrieve. Since this completion handler can run on any thread, we
1788                 // need to ensure that the async info is valid in the current apartment. _M_asyncInfo will be accessed via calls to 'this' inside
1789                 // _AsyncInit.
1790                 _M_asyncInfo = _ResultContext<_AsyncOperationType*>::_GetValue(_M_asyncInfo.Get(), _M_asyncInfoContext, false);
1791 #endif
1792                 return _M_CompletedHandler->Invoke(_M_asyncInfo.Get(), status);
1793             });
1794 #if _MSC_VER >= 1800
1795             return _M_asyncInfo.Get()->put_Completed(handler.Get());
1796 #else
1797             return _M_asyncInfo->put_Completed(handler.Get());
1798 #endif
1799         }
1800     };
1801 
1802     extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncOperationToAsyncOperationConverter[] = L"_IAsyncOperationToAsyncOperationConverter";
1803 
1804     /// <summary>
1805     ///     Class _IAsyncOperationToAsyncOperationConverter is used to convert an instance of IAsyncOperationWithProgress<T> into IAsyncOperation<T>
1806     /// </summary>
1807     template<typename _Result>
1808     struct _IAsyncOperationToAsyncOperationConverter :
1809         _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncOperation<_Result>,
1810         ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_Result>,
1811         typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperation<_Result>*>()))>::type>
1812     {
1813         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperation<_Result>*>()))>::type _Result_abi;
1814 
1815         InspectableClass(RuntimeClass_IAsyncOperationToAsyncOperationConverter, BaseTrust)
1816     public:
_IAsyncOperationToAsyncOperationConverterConcurrency_winrt::details::_IAsyncOperationToAsyncOperationConverter1817         _IAsyncOperationToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncOperation<_Result>* _Operation) :
1818             _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncOperation<_Result>,
1819             ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_Result>,
1820             _Result_abi>(_Operation) {}
1821     public:
GetResultsConcurrency_winrt::details::_IAsyncOperationToAsyncOperationConverter1822         virtual STDMETHODIMP GetResults(_Result_abi* results) override {
1823             if (!results) return E_POINTER;
1824 #if _MSC_VER >= 1800
1825             return _M_asyncInfo.Get()->GetResults(results);
1826 #else
1827             return _M_asyncInfo->GetResults(results);
1828 #endif
1829         }
1830     };
1831 
1832     extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncOperationWithProgressToAsyncOperationConverter[] = L"_IAsyncOperationWithProgressToAsyncOperationConverter";
1833 
1834     /// <summary>
1835     ///     Class _IAsyncOperationWithProgressToAsyncOperationConverter is used to convert an instance of IAsyncOperationWithProgress<T> into IAsyncOperation<T>
1836     /// </summary>
1837     template<typename _Result, typename _Progress>
1838     struct _IAsyncOperationWithProgressToAsyncOperationConverter :
1839     _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>,
1840         ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<_Result, _Progress>,
1841         typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>*>()))>::type>
1842     {
1843         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>*>()))>::type _Result_abi;
1844 
1845         InspectableClass(RuntimeClass_IAsyncOperationWithProgressToAsyncOperationConverter, BaseTrust)
1846     public:
_IAsyncOperationWithProgressToAsyncOperationConverterConcurrency_winrt::details::_IAsyncOperationWithProgressToAsyncOperationConverter1847         _IAsyncOperationWithProgressToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>* _Operation) :
1848             _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>,
1849             ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<_Result, _Progress>,
1850             _Result_abi>(_Operation) {}
1851     public:
GetResultsConcurrency_winrt::details::_IAsyncOperationWithProgressToAsyncOperationConverter1852         virtual STDMETHODIMP GetResults(_Result_abi* results) override {
1853             if (!results) return E_POINTER;
1854 #if _MSC_VER >= 1800
1855             return _M_asyncInfo.Get()->GetResults(results);
1856 #else
1857             return _M_asyncInfo->GetResults(results);
1858 #endif
1859         }
1860     };
1861 
1862     extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncActionToAsyncOperationConverter[] = L"_IAsyncActionToAsyncOperationConverter";
1863 
1864     /// <summary>
1865     ///     Class _IAsyncActionToAsyncOperationConverter is used to convert an instance of IAsyncAction into IAsyncOperation<_Unit_type>
1866     /// </summary>
1867     struct _IAsyncActionToAsyncOperationConverter :
1868     _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncAction,
1869         ABI::Windows::Foundation::IAsyncActionCompletedHandler,
1870         _Unit_type>
1871     {
1872         InspectableClass(RuntimeClass_IAsyncActionToAsyncOperationConverter, BaseTrust)
1873     public:
_IAsyncActionToAsyncOperationConverterConcurrency_winrt::details::_IAsyncActionToAsyncOperationConverter1874         _IAsyncActionToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncAction* _Operation) :
1875             _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncAction,
1876             ABI::Windows::Foundation::IAsyncActionCompletedHandler,
1877             _Unit_type>(_Operation) {}
1878 
1879     public:
GetResultsConcurrency_winrt::details::_IAsyncActionToAsyncOperationConverter1880         virtual STDMETHODIMP GetResults(details::_Unit_type* results)
1881         {
1882             if (!results) return E_POINTER;
1883             // Invoke GetResults on the IAsyncAction to allow exceptions to be thrown to higher layers before returning a dummy value.
1884 #if _MSC_VER >= 1800
1885             HRESULT hr = _M_asyncInfo.Get()->GetResults();
1886 #else
1887             HRESULT hr = _M_asyncInfo->GetResults();
1888 #endif
1889             if (SUCCEEDED(hr)) *results = _Unit_type();
1890             return hr;
1891         }
1892     };
1893 
1894     extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncActionWithProgressToAsyncOperationConverter[] = L"_IAsyncActionWithProgressToAsyncOperationConverter";
1895 
1896     /// <summary>
1897     ///     Class _IAsyncActionWithProgressToAsyncOperationConverter is used to convert an instance of IAsyncActionWithProgress into IAsyncOperation<_Unit_type>
1898     /// </summary>
1899     template<typename _Progress>
1900     struct _IAsyncActionWithProgressToAsyncOperationConverter :
1901     _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>,
1902         ABI::Windows::Foundation::IAsyncActionWithProgressCompletedHandler<_Progress>,
1903         _Unit_type>
1904     {
1905         InspectableClass(RuntimeClass_IAsyncActionWithProgressToAsyncOperationConverter, BaseTrust)
1906     public:
_IAsyncActionWithProgressToAsyncOperationConverterConcurrency_winrt::details::_IAsyncActionWithProgressToAsyncOperationConverter1907         _IAsyncActionWithProgressToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>* _Action) :
1908             _AsyncInfoImpl<ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>,
1909             ABI::Windows::Foundation::IAsyncActionWithProgressCompletedHandler<_Progress>,
1910             _Unit_type>(_Action) {}
1911     public:
GetResultsConcurrency_winrt::details::_IAsyncActionWithProgressToAsyncOperationConverter1912         virtual STDMETHODIMP GetResults(_Unit_type* results) override
1913         {
1914             if (!results) return E_POINTER;
1915             // Invoke GetResults on the IAsyncActionWithProgress to allow exceptions to be thrown before returning a dummy value.
1916 #if _MSC_VER >= 1800
1917             HRESULT hr = _M_asyncInfo.Get()->GetResults();
1918 #else
1919             HRESULT hr = _M_asyncInfo->GetResults();
1920 #endif
1921             if (SUCCEEDED(hr)) *results = _Unit_type();
1922             return hr;
1923         }
1924     };
1925 }
1926 
1927 /// <summary>
1928 ///     The <c>task_continuation_context</c> class allows you to specify where you would like a continuation to be executed.
1929 ///     It is only useful to use this class from a Windows Store app. For non-Windows Store apps, the task continuation's
1930 ///     execution context is determined by the runtime, and not configurable.
1931 /// </summary>
1932 /// <seealso cref="task Class"/>
1933 /**/
1934 class task_continuation_context : public details::_ContextCallback
1935 {
1936 public:
1937 
1938     /// <summary>
1939     ///     Creates the default task continuation context.
1940     /// </summary>
1941     /// <returns>
1942     ///     The default continuation context.
1943     /// </returns>
1944     /// <remarks>
1945     ///     The default context is used if you don't specifiy a continuation context when you call the <c>then</c> method. In Windows
1946     ///     applications for Windows 7 and below, as well as desktop applications on Windows 8 and higher, the runtime determines where
1947     ///     task continuations will execute. However, in a Windows Store app, the default continuation context for a continuation on an
1948     ///     apartment aware task is the apartment where <c>then</c> is invoked.
1949     ///     <para>An apartment aware task is a task that unwraps a Windows Runtime <c>IAsyncInfo</c> interface, or a task that is descended from such
1950     ///     a task. Therefore, if you schedule a continuation on an apartment aware task in a Windows Runtime STA, the continuation will execute in
1951     ///     that STA.</para>
1952     ///     <para>A continuation on a non-apartment aware task will execute in a context the Runtime chooses.</para>
1953     /// </remarks>
1954     /**/
use_default()1955     static task_continuation_context use_default()
1956     {
1957         // The callback context is created with the context set to CaptureDeferred and resolved when it is used in .then()
1958         return task_continuation_context(true); // sets it to deferred, is resolved in the constructor of _ContinuationTaskHandle
1959     }
1960 
1961     /// <summary>
1962     ///     Creates a task continuation context which allows the Runtime to choose the execution context for a continuation.
1963     /// </summary>
1964     /// <returns>
1965     ///     A task continuation context that represents an arbitrary location.
1966     /// </returns>
1967     /// <remarks>
1968     ///     When this continuation context is used the continuation will execute in a context the runtime chooses even if the antecedent task
1969     ///     is apartment aware.
1970     ///     <para><c>use_arbitrary</c> can be used to turn off the default behavior for a continuation on an apartment
1971     ///     aware task created in an STA. </para>
1972     ///     <para>This method is only available to Windows Store apps.</para>
1973     /// </remarks>
1974     /**/
use_arbitrary()1975     static task_continuation_context use_arbitrary()
1976     {
1977         task_continuation_context _Arbitrary(true);
1978         _Arbitrary._Resolve(false);
1979         return _Arbitrary;
1980     }
1981 
1982     /// <summary>
1983     ///     Returns a task continuation context object that represents the current execution context.
1984     /// </summary>
1985     /// <returns>
1986     ///     The current execution context.
1987     /// </returns>
1988     /// <remarks>
1989     ///     This method captures the caller's Windows Runtime context so that continuations can be executed in the right apartment.
1990     ///     <para>The value returned by <c>use_current</c> can be used to indicate to the Runtime that the continuation should execute in
1991     ///     the captured context (STA vs MTA) regardless of whether or not the antecedent task is apartment aware. An apartment aware task is
1992     ///     a task that unwraps a Windows Runtime <c>IAsyncInfo</c> interface, or a task that is descended from such a task. </para>
1993     ///     <para>This method is only available to Windows Store apps.</para>
1994     /// </remarks>
1995     /**/
use_current()1996     static task_continuation_context use_current()
1997     {
1998         task_continuation_context _Current(true);
1999         _Current._Resolve(true);
2000         return _Current;
2001     }
2002 
2003 private:
2004 
task_continuation_context(bool _DeferCapture=false)2005     task_continuation_context(bool _DeferCapture = false) : details::_ContextCallback(_DeferCapture)
2006     {
2007     }
2008 };
2009 
2010 #if _MSC_VER >= 1800
2011 class task_options;
2012 namespace details
2013 {
2014     struct _Internal_task_options
2015     {
2016         bool _M_hasPresetCreationCallstack;
2017         _TaskCreationCallstack _M_presetCreationCallstack;
2018 
_set_creation_callstackConcurrency_winrt::details::_Internal_task_options2019         void _set_creation_callstack(const _TaskCreationCallstack &_callstack)
2020         {
2021             _M_hasPresetCreationCallstack = true;
2022             _M_presetCreationCallstack = _callstack;
2023         }
_Internal_task_optionsConcurrency_winrt::details::_Internal_task_options2024         _Internal_task_options()
2025         {
2026             _M_hasPresetCreationCallstack = false;
2027         }
2028     };
2029 
2030     inline _Internal_task_options &_get_internal_task_options(task_options &options);
2031     inline const _Internal_task_options &_get_internal_task_options(const task_options &options);
2032 }
2033 /// <summary>
2034 ///     Represents the allowed options for creating a task
2035 /// </summary>
2036 class task_options
2037 {
2038 public:
2039 
2040 
2041     /// <summary>
2042     ///     Default list of task creation options
2043     /// </summary>
task_options()2044     task_options()
2045         : _M_Scheduler(Concurrency::get_ambient_scheduler()),
2046         _M_CancellationToken(Concurrency::cancellation_token::none()),
2047         _M_ContinuationContext(task_continuation_context::use_default()),
2048         _M_HasCancellationToken(false),
2049         _M_HasScheduler(false)
2050     {
2051     }
2052 
2053     /// <summary>
2054     ///     Task option that specify a cancellation token
2055     /// </summary>
task_options(Concurrency::cancellation_token _Token)2056     task_options(Concurrency::cancellation_token _Token)
2057         : _M_Scheduler(Concurrency::get_ambient_scheduler()),
2058         _M_CancellationToken(_Token),
2059         _M_ContinuationContext(task_continuation_context::use_default()),
2060         _M_HasCancellationToken(true),
2061         _M_HasScheduler(false)
2062     {
2063     }
2064 
2065     /// <summary>
2066     ///     Task option that specify a continuation context. This is valid only for continuations (then)
2067     /// </summary>
task_options(task_continuation_context _ContinuationContext)2068     task_options(task_continuation_context _ContinuationContext)
2069         : _M_Scheduler(Concurrency::get_ambient_scheduler()),
2070         _M_CancellationToken(Concurrency::cancellation_token::none()),
2071         _M_ContinuationContext(_ContinuationContext),
2072         _M_HasCancellationToken(false),
2073         _M_HasScheduler(false)
2074     {
2075     }
2076 
2077     /// <summary>
2078     ///     Task option that specify a cancellation token and a continuation context. This is valid only for continuations (then)
2079     /// </summary>
task_options(Concurrency::cancellation_token _Token,task_continuation_context _ContinuationContext)2080     task_options(Concurrency::cancellation_token _Token, task_continuation_context _ContinuationContext)
2081         : _M_Scheduler(Concurrency::get_ambient_scheduler()),
2082         _M_CancellationToken(_Token),
2083         _M_ContinuationContext(_ContinuationContext),
2084         _M_HasCancellationToken(false),
2085         _M_HasScheduler(false)
2086     {
2087     }
2088 
2089     /// <summary>
2090     ///     Task option that specify a scheduler with shared lifetime
2091     /// </summary>
2092     template<typename _SchedType>
task_options(std::shared_ptr<_SchedType> _Scheduler)2093     task_options(std::shared_ptr<_SchedType> _Scheduler)
2094         : _M_Scheduler(std::move(_Scheduler)),
2095         _M_CancellationToken(cancellation_token::none()),
2096         _M_ContinuationContext(task_continuation_context::use_default()),
2097         _M_HasCancellationToken(false),
2098         _M_HasScheduler(true)
2099     {
2100     }
2101 
2102     /// <summary>
2103     ///     Task option that specify a scheduler reference
2104     /// </summary>
task_options(Concurrency::scheduler_interface & _Scheduler)2105     task_options(Concurrency::scheduler_interface& _Scheduler)
2106         : _M_Scheduler(&_Scheduler),
2107         _M_CancellationToken(Concurrency::cancellation_token::none()),
2108         _M_ContinuationContext(task_continuation_context::use_default()),
2109         _M_HasCancellationToken(false),
2110         _M_HasScheduler(true)
2111     {
2112     }
2113 
2114     /// <summary>
2115     ///     Task option that specify a scheduler
2116     /// </summary>
task_options(Concurrency::scheduler_ptr _Scheduler)2117     task_options(Concurrency::scheduler_ptr _Scheduler)
2118         : _M_Scheduler(std::move(_Scheduler)),
2119         _M_CancellationToken(Concurrency::cancellation_token::none()),
2120         _M_ContinuationContext(task_continuation_context::use_default()),
2121         _M_HasCancellationToken(false),
2122         _M_HasScheduler(true)
2123     {
2124     }
2125 
2126     /// <summary>
2127     ///     Task option copy constructor
2128     /// </summary>
task_options(const task_options & _TaskOptions)2129     task_options(const task_options& _TaskOptions)
2130         : _M_Scheduler(_TaskOptions.get_scheduler()),
2131         _M_CancellationToken(_TaskOptions.get_cancellation_token()),
2132         _M_ContinuationContext(_TaskOptions.get_continuation_context()),
2133         _M_HasCancellationToken(_TaskOptions.has_cancellation_token()),
2134         _M_HasScheduler(_TaskOptions.has_scheduler())
2135     {
2136     }
2137 
2138     /// <summary>
2139     ///     Sets the given token in the options
2140     /// </summary>
set_cancellation_token(Concurrency::cancellation_token _Token)2141     void set_cancellation_token(Concurrency::cancellation_token _Token)
2142     {
2143         _M_CancellationToken = _Token;
2144         _M_HasCancellationToken = true;
2145     }
2146 
2147     /// <summary>
2148     ///     Sets the given continuation context in the options
2149     /// </summary>
set_continuation_context(task_continuation_context _ContinuationContext)2150     void set_continuation_context(task_continuation_context _ContinuationContext)
2151     {
2152         _M_ContinuationContext = _ContinuationContext;
2153     }
2154 
2155     /// <summary>
2156     ///     Indicates whether a cancellation token was specified by the user
2157     /// </summary>
has_cancellation_token() const2158     bool has_cancellation_token() const
2159     {
2160         return _M_HasCancellationToken;
2161     }
2162 
2163     /// <summary>
2164     ///     Returns the cancellation token
2165     /// </summary>
get_cancellation_token() const2166     Concurrency::cancellation_token get_cancellation_token() const
2167     {
2168         return _M_CancellationToken;
2169     }
2170 
2171     /// <summary>
2172     ///     Returns the continuation context
2173     /// </summary>
get_continuation_context() const2174     task_continuation_context get_continuation_context() const
2175     {
2176         return _M_ContinuationContext;
2177     }
2178 
2179     /// <summary>
2180     ///     Indicates whether a scheduler n was specified by the user
2181     /// </summary>
has_scheduler() const2182     bool has_scheduler() const
2183     {
2184         return _M_HasScheduler;
2185     }
2186 
2187     /// <summary>
2188     ///     Returns the scheduler
2189     /// </summary>
get_scheduler() const2190     Concurrency::scheduler_ptr get_scheduler() const
2191     {
2192         return _M_Scheduler;
2193     }
2194 
2195 private:
2196 
2197     task_options const& operator=(task_options const& _Right);
2198     friend details::_Internal_task_options &details::_get_internal_task_options(task_options &);
2199     friend const details::_Internal_task_options &details::_get_internal_task_options(const task_options &);
2200 
2201     Concurrency::scheduler_ptr _M_Scheduler;
2202     Concurrency::cancellation_token _M_CancellationToken;
2203     task_continuation_context _M_ContinuationContext;
2204     details::_Internal_task_options _M_InternalTaskOptions;
2205     bool _M_HasCancellationToken;
2206     bool _M_HasScheduler;
2207 };
2208 #endif
2209 
2210 namespace details
2211 {
2212 #if _MSC_VER >= 1800
_get_internal_task_options(task_options & options)2213     inline _Internal_task_options & _get_internal_task_options(task_options &options)
2214     {
2215         return options._M_InternalTaskOptions;
2216     }
_get_internal_task_options(const task_options & options)2217     inline const _Internal_task_options & _get_internal_task_options(const task_options &options)
2218     {
2219         return options._M_InternalTaskOptions;
2220     }
2221 #endif
2222     struct _Task_impl_base;
2223     template<typename _ReturnType> struct _Task_impl;
2224 
2225     template<typename _ReturnType>
2226     struct _Task_ptr
2227     {
2228         typedef std::shared_ptr<_Task_impl<_ReturnType>> _Type;
2229 #if _MSC_VER >= 1800
_MakeConcurrency_winrt::details::_Task_ptr2230         static _Type _Make(Concurrency::details::_CancellationTokenState * _Ct, Concurrency::scheduler_ptr _Scheduler_arg) { return std::make_shared<_Task_impl<_ReturnType>>(_Ct, _Scheduler_arg); }
2231 #else
_MakeConcurrency_winrt::details::_Task_ptr2232         static _Type _Make(Concurrency::details::_CancellationTokenState * _Ct) { return std::make_shared<_Task_impl<_ReturnType>>(_Ct); }
2233 #endif
2234     };
2235 #if _MSC_VER >= 1800
2236     typedef Concurrency::details::_TaskCollection_t::_TaskProcHandle_t _UnrealizedChore_t;
2237     typedef _UnrealizedChore_t _UnrealizedChore;
2238     typedef Concurrency::extensibility::scoped_critical_section_t scoped_lock;
2239     typedef Concurrency::extensibility::critical_section_t critical_section;
2240     typedef Concurrency::details::atomic_size_t atomic_size_t;
2241 #else
2242     typedef Concurrency::details::_UnrealizedChore _UnrealizedChore;
2243     typedef Concurrency::critical_section::scoped_lock scoped_lock;
2244     typedef Concurrency::critical_section critical_section;
2245     typedef volatile size_t atomic_size_t;
2246 #endif
2247     typedef std::shared_ptr<_Task_impl_base> _Task_ptr_base;
2248     // The weak-typed base task handler for continuation tasks.
2249     struct _ContinuationTaskHandleBase : _UnrealizedChore
2250     {
2251         _ContinuationTaskHandleBase * _M_next;
2252         task_continuation_context _M_continuationContext;
2253         bool _M_isTaskBasedContinuation;
2254 
2255         // This field gives inlining scheduling policy for current chore.
2256         _TaskInliningMode _M_inliningMode;
2257 
2258         virtual _Task_ptr_base _GetTaskImplBase() const = 0;
2259 
_ContinuationTaskHandleBaseConcurrency_winrt::details::_ContinuationTaskHandleBase2260         _ContinuationTaskHandleBase() :
2261             _M_next(nullptr), _M_isTaskBasedContinuation(false), _M_continuationContext(task_continuation_context::use_default()), _M_inliningMode(Concurrency::details::_NoInline)
2262         {
2263         }
~_ContinuationTaskHandleBaseConcurrency_winrt::details::_ContinuationTaskHandleBase2264         virtual ~_ContinuationTaskHandleBase() {}
2265     };
2266 #if _MSC_VER >= 1800
2267 #if _PPLTASK_ASYNC_LOGGING
2268     // GUID used for identifying causality logs from PPLTask
2269     const ::Platform::Guid _PPLTaskCausalityPlatformID(0x7A76B220, 0xA758, 0x4E6E, 0xB0, 0xE0, 0xD7, 0xC6, 0xD7, 0x4A, 0x88, 0xFE);
2270 
2271     __declspec(selectany) volatile long _isCausalitySupported = 0;
2272 
_IsCausalitySupported()2273     inline bool _IsCausalitySupported()
2274     {
2275 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
2276         if (_isCausalitySupported == 0)
2277         {
2278             long _causality = 1;
2279             OSVERSIONINFOEX _osvi = {};
2280             _osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
2281 
2282             // The Causality is supported on Windows version higher than Windows 8
2283             _osvi.dwMajorVersion = 6;
2284             _osvi.dwMinorVersion = 3;
2285 
2286             DWORDLONG _conditionMask = 0;
2287             VER_SET_CONDITION(_conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
2288             VER_SET_CONDITION(_conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
2289 
2290             if (::VerifyVersionInfo(&_osvi, VER_MAJORVERSION | VER_MINORVERSION, _conditionMask))
2291             {
2292                 _causality = 2;
2293             }
2294 
2295             _isCausalitySupported = _causality;
2296             return _causality == 2;
2297         }
2298 
2299         return _isCausalitySupported == 2 ? true : false;
2300 #else
2301         return true;
2302 #endif
2303     }
2304 
2305     // Stateful logger rests inside task_impl_base.
2306     struct _TaskEventLogger
2307     {
2308         _Task_impl_base *_M_task;
2309         bool _M_scheduled;
2310         bool _M_taskPostEventStarted;
2311 
2312         // Log before scheduling task
_LogScheduleTaskConcurrency_winrt::details::_TaskEventLogger2313         void _LogScheduleTask(bool _isContinuation)
2314         {
2315             if (details::_IsCausalitySupported())
2316             {
2317                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCreation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2318                     _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
2319                     _isContinuation ? "Concurrency::PPLTask::ScheduleContinuationTask" : "Concurrency::PPLTask::ScheduleTask", 0);
2320                 _M_scheduled = true;
2321             }
2322         }
2323 
2324         // It will log the cancel event but not canceled state. _LogTaskCompleted will log the terminal state, which includes cancel state.
_LogCancelTaskConcurrency_winrt::details::_TaskEventLogger2325         void _LogCancelTask()
2326         {
2327             if (details::_IsCausalitySupported())
2328             {
2329                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationRelation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Important, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2330                     _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalityRelation::Cancel);
2331 
2332             }
2333         }
2334 
2335         // Log when task reaches terminal state. Note: the task can reach a terminal state (by cancellation or exception) without having run
2336         void _LogTaskCompleted();
2337 
2338         // Log when task body (which includes user lambda and other scheduling code) begin to run
_LogTaskExecutionStartedConcurrency_winrt::details::_TaskEventLogger2339         void _LogTaskExecutionStarted() { }
2340 
2341         // Log when task body finish executing
_LogTaskExecutionCompletedConcurrency_winrt::details::_TaskEventLogger2342         void _LogTaskExecutionCompleted()
2343         {
2344             if (_M_taskPostEventStarted && details::_IsCausalitySupported())
2345             {
2346                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2347                     ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
2348             }
2349         }
2350 
2351         // Log right before user lambda being invoked
_LogWorkItemStartedConcurrency_winrt::details::_TaskEventLogger2352         void _LogWorkItemStarted()
2353         {
2354             if (details::_IsCausalitySupported())
2355             {
2356                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2357                     _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
2358             }
2359         }
2360 
2361         // Log right after user lambda being invoked
_LogWorkItemCompletedConcurrency_winrt::details::_TaskEventLogger2362         void _LogWorkItemCompleted()
2363         {
2364             if (details::_IsCausalitySupported())
2365             {
2366                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2367                     ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
2368 
2369                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2370                     _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
2371                 _M_taskPostEventStarted = true;
2372             }
2373         }
2374 
_TaskEventLoggerConcurrency_winrt::details::_TaskEventLogger2375         _TaskEventLogger(_Task_impl_base *_task) : _M_task(_task)
2376         {
2377             _M_scheduled = false;
2378             _M_taskPostEventStarted = false;
2379         }
2380     };
2381 
2382     // Exception safe logger for user lambda
2383     struct _TaskWorkItemRAIILogger
2384     {
2385         _TaskEventLogger &_M_logger;
_TaskWorkItemRAIILoggerConcurrency_winrt::details::_TaskWorkItemRAIILogger2386         _TaskWorkItemRAIILogger(_TaskEventLogger &_taskHandleLogger) : _M_logger(_taskHandleLogger)
2387         {
2388             _M_logger._LogWorkItemStarted();
2389         }
2390 
~_TaskWorkItemRAIILoggerConcurrency_winrt::details::_TaskWorkItemRAIILogger2391         ~_TaskWorkItemRAIILogger()
2392         {
2393             _M_logger._LogWorkItemCompleted();
2394         }
2395         _TaskWorkItemRAIILogger &operator =(const _TaskWorkItemRAIILogger &); // cannot be assigned
2396     };
2397 
2398 #else
_LogCancelTask(_Task_impl_base *)2399     inline void _LogCancelTask(_Task_impl_base *) {}
2400     struct _TaskEventLogger
2401     {
_LogScheduleTaskConcurrency_winrt::details::_TaskEventLogger2402         void _LogScheduleTask(bool) {}
_LogCancelTaskConcurrency_winrt::details::_TaskEventLogger2403         void _LogCancelTask() {}
_LogWorkItemStartedConcurrency_winrt::details::_TaskEventLogger2404         void _LogWorkItemStarted() {}
_LogWorkItemCompletedConcurrency_winrt::details::_TaskEventLogger2405         void _LogWorkItemCompleted() {}
_LogTaskExecutionStartedConcurrency_winrt::details::_TaskEventLogger2406         void _LogTaskExecutionStarted() {}
_LogTaskExecutionCompletedConcurrency_winrt::details::_TaskEventLogger2407         void _LogTaskExecutionCompleted() {}
_LogTaskCompletedConcurrency_winrt::details::_TaskEventLogger2408         void _LogTaskCompleted() {}
_TaskEventLoggerConcurrency_winrt::details::_TaskEventLogger2409         _TaskEventLogger(_Task_impl_base *) {}
2410     };
2411     struct _TaskWorkItemRAIILogger
2412     {
_TaskWorkItemRAIILoggerConcurrency_winrt::details::_TaskWorkItemRAIILogger2413         _TaskWorkItemRAIILogger(_TaskEventLogger &) {}
2414     };
2415 #endif
2416 #endif
2417     /// <summary>
2418     ///     The _PPLTaskHandle is the strong-typed task handle base. All user task functions need to be wrapped in this task handler
2419     ///     to be executable by PPL. By deriving from a different _BaseTaskHandle, it can be used for both initial tasks and continuation tasks.
2420     ///     For initial tasks, _PPLTaskHandle will be derived from _UnrealizedChore, and for continuation tasks, it will be derived from
2421     ///     _ContinuationTaskHandleBase. The life time of the _PPLTaskHandle object is be managed by runtime if task handle is scheduled.
2422     /// </summary>
2423     /// <typeparam name="_ReturnType">
2424     ///     The result type of the _Task_impl.
2425     /// </typeparam>
2426     /// <typeparam name="_DerivedTaskHandle">
2427     ///     The derived task handle class. The <c>operator ()</c> needs to be implemented.
2428     /// </typeparam>
2429     /// <typeparam name="_BaseTaskHandle">
2430     ///     The base class from which _PPLTaskHandle should be derived. This is either _UnrealizedChore or _ContinuationTaskHandleBase.
2431     /// </typeparam>
2432     template<typename _ReturnType, typename _DerivedTaskHandle, typename _BaseTaskHandle>
2433     struct _PPLTaskHandle : _BaseTaskHandle
2434     {
_PPLTaskHandleConcurrency_winrt::details::_PPLTaskHandle2435         _PPLTaskHandle(const typename _Task_ptr<_ReturnType>::_Type & _PTask) : _M_pTask(_PTask)
2436         {
2437 #if _MSC_VER < 1800
2438             m_pFunction = reinterpret_cast <Concurrency::TaskProc> (&_UnrealizedChore::_InvokeBridge<_PPLTaskHandle>);
2439             _SetRuntimeOwnsLifetime(true);
2440 #endif
2441         }
~_PPLTaskHandleConcurrency_winrt::details::_PPLTaskHandle2442         virtual ~_PPLTaskHandle() {
2443 #if _MSC_VER >= 1800
2444             // Here is the sink of all task completion code paths
2445             _M_pTask->_M_taskEventLogger._LogTaskCompleted();
2446 #endif
2447         }
2448 #if _MSC_VER >= 1800
invokeConcurrency_winrt::details::_PPLTaskHandle2449         virtual void invoke() const
2450 #else
2451         void operator()() const
2452 #endif
2453         {
2454             // All exceptions should be rethrown to finish cleanup of the task collection. They will be caught and handled
2455             // by the runtime.
2456             _CONCRT_ASSERT(_M_pTask != nullptr);
2457             if (!_M_pTask->_TransitionedToStarted()) {
2458 #if _MSC_VER >= 1800
2459                 static_cast<const _DerivedTaskHandle *>(this)->_SyncCancelAndPropagateException();
2460 #endif
2461                 return;
2462             }
2463 #if _MSC_VER >= 1800
2464             _M_pTask->_M_taskEventLogger._LogTaskExecutionStarted();
2465 #endif
2466             try
2467             {
2468                 // All derived task handle must implement this contract function.
2469                 static_cast<const _DerivedTaskHandle *>(this)->_Perform();
2470             }
2471             catch (const Concurrency::task_canceled &)
2472             {
2473                 _M_pTask->_Cancel(true);
2474 #if _MSC_VER < 1800
2475                 throw;
2476 #endif
2477             }
2478             catch (const Concurrency::details::_Interruption_exception &)
2479             {
2480                 _M_pTask->_Cancel(true);
2481 #if _MSC_VER < 1800
2482                 throw;
2483 #endif
2484             }
2485             catch (IRestrictedErrorInfo*& _E)
2486             {
2487                 _M_pTask->_CancelWithException(_E);
2488 #if _MSC_VER < 1800
2489                 throw;
2490 #endif
2491             }
2492             catch (...)
2493             {
2494                 _M_pTask->_CancelWithException(std::current_exception());
2495 #if _MSC_VER < 1800
2496                 throw;
2497 #endif
2498             }
2499 #if _MSC_VER >= 1800
2500             _M_pTask->_M_taskEventLogger._LogTaskExecutionCompleted();
2501 #endif
2502         }
2503 
2504         // Cast _M_pTask pointer to "type-less" _Task_impl_base pointer, which can be used in _ContinuationTaskHandleBase.
2505         // The return value should be automatically optimized by R-value ref.
_GetTaskImplBaseConcurrency_winrt::details::_PPLTaskHandle2506         _Task_ptr_base _GetTaskImplBase() const
2507         {
2508             return _M_pTask;
2509         }
2510 
2511         typename _Task_ptr<_ReturnType>::_Type _M_pTask;
2512 
2513     private:
2514         _PPLTaskHandle const & operator=(_PPLTaskHandle const&);    // no assignment operator
2515     };
2516 
2517     /// <summary>
2518     ///     The base implementation of a first-class task. This class contains all the non-type specific
2519     ///     implementation details of the task.
2520     /// </summary>
2521     /**/
2522     struct _Task_impl_base
2523     {
2524         enum _TaskInternalState
2525         {
2526             // Tracks the state of the task, rather than the task collection on which the task is scheduled
2527             _Created,
2528             _Started,
2529             _PendingCancel,
2530             _Completed,
2531             _Canceled
2532         };
2533 #if _MSC_VER >= 1800
_Task_impl_baseConcurrency_winrt::details::_Task_impl_base2534         _Task_impl_base(Concurrency::details::_CancellationTokenState * _PTokenState, Concurrency::scheduler_ptr _Scheduler_arg)
2535             : _M_TaskState(_Created),
2536             _M_fFromAsync(false), _M_fUnwrappedTask(false),
2537             _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_TaskCollection(_Scheduler_arg),
2538             _M_taskEventLogger(this)
2539 #else
2540         _Task_impl_base(Concurrency::details::_CancellationTokenState * _PTokenState) : _M_TaskState(_Created),
2541             _M_fFromAsync(false), _M_fRuntimeAggregate(false), _M_fUnwrappedTask(false),
2542             _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_pTaskCollection(nullptr),
2543             _M_pTaskCreationAddressHint(nullptr)
2544 #endif
2545         {
2546             // Set cancelation token
2547             _M_pTokenState = _PTokenState;
2548             _CONCRT_ASSERT(_M_pTokenState != nullptr);
2549             if (_M_pTokenState != Concurrency::details::_CancellationTokenState::_None())
2550                 _M_pTokenState->_Reference();
2551 
2552         }
2553 
~_Task_impl_baseConcurrency_winrt::details::_Task_impl_base2554         virtual ~_Task_impl_base()
2555         {
2556             _CONCRT_ASSERT(_M_pTokenState != nullptr);
2557             if (_M_pTokenState != Concurrency::details::_CancellationTokenState::_None())
2558             {
2559                 _M_pTokenState->_Release();
2560             }
2561 #if _MSC_VER < 1800
2562             if (_M_pTaskCollection != nullptr)
2563             {
2564                 _M_pTaskCollection->_Release();
2565                 _M_pTaskCollection = nullptr;
2566             }
2567 #endif
2568         }
2569 
_WaitConcurrency_winrt::details::_Task_impl_base2570         task_status _Wait()
2571         {
2572             bool _DoWait = true;
2573 
2574             if (_IsNonBlockingThread())
2575             {
2576                 // In order to prevent Windows Runtime STA threads from blocking the UI, calling task.wait() task.get() is illegal
2577                 // if task has not been completed.
2578                 if (!_IsCompleted() && !_IsCanceled())
2579                 {
2580                     throw Concurrency::invalid_operation("Illegal to wait on a task in a Windows Runtime STA");
2581                 }
2582                 else
2583                 {
2584                     // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestors's task group. If a continuation
2585                     // needs to be marshalled to a different apartment, instead of scheduling, we make a synchronous cross apartment COM
2586                     // call to execute the continuation. If it then happens to do something which waits on the ancestor (say it calls .get(), which
2587                     // task based continuations are wont to do), waiting on the task group results in on the chore that is making this
2588                     // synchronous callback, which causes a deadlock. To avoid this, we test the state ancestor's event , and we will NOT wait on
2589                     // if it has finished execution (which means now we are on the inline synchronous callback).
2590                     _DoWait = false;
2591                 }
2592             }
2593             if (_DoWait)
2594             {
2595 #if _MSC_VER < 1800
2596                 // Wait for the task to be actually scheduled, otherwise the underlying task collection
2597                 // might not be created yet. If we don't wait, we will miss the chance to inline this task.
2598                 _M_Scheduled.wait();
2599 
2600 
2601                 // A PPL task created by a task_completion_event does not have an underlying TaskCollection. For
2602                 // These tasks, a call to wait should wait for the event to be set. The TaskCollection must either
2603                 // be nullptr or allocated (the setting of _M_Scheduled) ensures that.
2604 #endif
2605                 // If this task was created from a Windows Runtime async operation, do not attempt to inline it. The
2606                 // async operation will take place on a thread in the appropriate apartment Simply wait for the completed
2607                 // event to be set.
2608 #if _MSC_VER >= 1800
2609                 if (_M_fFromAsync)
2610 #else
2611                 if ((_M_pTaskCollection == nullptr) || _M_fFromAsync)
2612 #endif
2613                 {
2614 #if _MSC_VER >= 1800
2615                     _M_TaskCollection._Wait();
2616 #else
2617                     _M_Completed.wait();
2618 #endif
2619                 }
2620                 else
2621                 {
2622                     // Wait on the task collection to complete. The task collection is guaranteed to still be
2623                     // valid since the task must be still within scope so that the _Task_impl_base destructor
2624                     // has not yet been called. This call to _Wait potentially inlines execution of work.
2625                     try
2626                     {
2627                         // Invoking wait on a task collection resets the state of the task collection. This means that
2628                         // if the task collection itself were canceled, or had encountered an exception, only the first
2629                         // call to wait will receive this status. However, both cancellation and exceptions flowing through
2630                         // tasks set state in the task impl itself.
2631 
2632                         // When it returns cancelled, either work chore or the cancel thread should already have set task's state
2633                         // properly -- cancelled state or completed state (because there was no interruption point).
2634                         // For tasks with unwrapped tasks, we should not change the state of current task, since the unwrapped task are still running.
2635 #if _MSC_VER >= 1800
2636                         _M_TaskCollection._RunAndWait();
2637 #else
2638                         _M_pTaskCollection->_RunAndWait();
2639 #endif
2640                     }
2641                     catch (Concurrency::details::_Interruption_exception&)
2642                     {
2643                         // The _TaskCollection will never be an interruption point since it has a none token.
2644                         _CONCRT_ASSERT(false);
2645                     }
2646                     catch (Concurrency::task_canceled&)
2647                     {
2648                         // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
2649                         // must be called from code that is executed within the task (throwing it from parallel work created by and waited
2650                         // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
2651                         // the exception and canceled the task. Swallow the exception here.
2652                         _CONCRT_ASSERT(_IsCanceled());
2653                     }
2654                     catch (IRestrictedErrorInfo*& _E)
2655                     {
2656                         // Its possible the task body hasn't seen the exception, if so we need to cancel with exception here.
2657                         if(!_HasUserException())
2658                         {
2659                             _CancelWithException(_E);
2660                         }
2661                         // Rethrow will mark the exception as observed.
2662                         _M_exceptionHolder->_RethrowUserException();
2663                     }
2664                     catch (...)
2665                     {
2666                         // Its possible the task body hasn't seen the exception, if so we need to cancel with exception here.
2667                         if (!_HasUserException())
2668                         {
2669                             _CancelWithException(std::current_exception());
2670                         }
2671                         // Rethrow will mark the exception as observed.
2672                         _M_exceptionHolder->_RethrowUserException();
2673                     }
2674 
2675                     // If the lambda body for this task (executed or waited upon in _RunAndWait above) happened to return a task
2676                     // which is to be unwrapped and plumbed to the output of this task, we must not only wait on the lambda body, we must
2677                     // wait on the **INNER** body. It is in theory possible that we could inline such if we plumb a series of things through;
2678                     // however, this takes the tact of simply waiting upon the completion signal.
2679                     if (_M_fUnwrappedTask)
2680                     {
2681 #if _MSC_VER >= 1800
2682                         _M_TaskCollection._Wait();
2683 #else
2684                         _M_Completed.wait();
2685 #endif
2686                     }
2687                 }
2688             }
2689 
2690             if (_HasUserException())
2691             {
2692                 _M_exceptionHolder->_RethrowUserException();
2693             }
2694             else if (_IsCanceled())
2695             {
2696                 return Concurrency::canceled;
2697             }
2698             _CONCRT_ASSERT(_IsCompleted());
2699             return Concurrency::completed;
2700         }
2701         /// <summary>
2702         ///     Requests cancellation on the task and schedules continuations if the task can be transitioned to a terminal state.
2703         /// </summary>
2704         /// <param name="_SynchronousCancel">
2705         ///     Set to true if the cancel takes place as a result of the task body encountering an exception, or because an ancestor or task_completion_event the task
2706         ///     was registered with were canceled with an exception. A synchronous cancel is one that assures the task could not be running on a different thread at
2707         ///     the time the cancellation is in progress. An asynchronous cancel is one where the thread performing the cancel has no control over the thread that could
2708         ///     be executing the task, that is the task could execute concurrently while the cancellation is in progress.
2709         /// </param>
2710         /// <param name="_UserException">
2711         ///     Whether an exception other than the internal runtime cancellation exceptions caused this cancellation.
2712         /// </param>
2713         /// <param name="_PropagatedFromAncestor">
2714         ///     Whether this exception came from an ancestor task or a task_completion_event as opposed to an exception that was encountered by the task itself. Only valid when
2715         ///     _UserException is set to true.
2716         /// </param>
2717         /// <param name="_ExHolder">
2718         ///     The exception holder that represents the exception. Only valid when _UserException is set to true.
2719         /// </param>
2720         virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder>& _ExHolder) = 0;
2721 
_CancelConcurrency_winrt::details::_Task_impl_base2722         bool _Cancel(bool _SynchronousCancel)
2723         {
2724             // Send in a dummy value for exception. It is not used when the first parameter is false.
2725             return _CancelAndRunContinuations(_SynchronousCancel, false, false, _M_exceptionHolder);
2726         }
2727 
_CancelWithExceptionHolderConcurrency_winrt::details::_Task_impl_base2728         bool _CancelWithExceptionHolder(const std::shared_ptr<_ExceptionHolder>& _ExHolder, bool _PropagatedFromAncestor)
2729         {
2730             // This task was canceled because an ancestor task encountered an exception.
2731             return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder);
2732         }
2733 
_CancelWithExceptionConcurrency_winrt::details::_Task_impl_base2734         bool _CancelWithException(IRestrictedErrorInfo*& _Exception)
2735         {
2736             // This task was canceled because the task body encountered an exception.
2737             _CONCRT_ASSERT(!_HasUserException());
2738 #if _MSC_VER >= 1800
2739             return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
2740 #else
2741             return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationAddressHint()));
2742 #endif
2743         }
_CancelWithExceptionConcurrency_winrt::details::_Task_impl_base2744         bool _CancelWithException(const std::exception_ptr& _Exception)
2745         {
2746             // This task was canceled because the task body encountered an exception.
2747             _CONCRT_ASSERT(!_HasUserException());
2748 #if _MSC_VER >= 1800
2749             return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
2750 #else
2751             return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationAddressHint()));
2752 #endif
2753         }
2754 
2755 #if _MSC_VER >= 1800
_RegisterCancellationConcurrency_winrt::details::_Task_impl_base2756         void _RegisterCancellation(std::weak_ptr<_Task_impl_base> _WeakPtr)
2757 #else
2758         void _RegisterCancellation()
2759 #endif
2760         {
2761             _CONCRT_ASSERT(Concurrency::details::_CancellationTokenState::_IsValid(_M_pTokenState));
2762 #if _MSC_VER >= 1800
2763             auto _CancellationCallback = [_WeakPtr](){
2764                 // Taking ownership of the task prevents dead lock during destruction
2765                 // if the destructor waits for the cancellations to be finished
2766                 auto _task = _WeakPtr.lock();
2767                 if (_task != nullptr)
2768                     _task->_Cancel(false);
2769             };
2770 
2771             _M_pRegistration = new Concurrency::details::_CancellationTokenCallback<decltype(_CancellationCallback)>(_CancellationCallback);
2772             _M_pTokenState->_RegisterCallback(_M_pRegistration);
2773 #else
2774             _M_pRegistration = _M_pTokenState->_RegisterCallback(reinterpret_cast<Concurrency::TaskProc>(&_CancelViaToken), (_Task_impl_base *)this);
2775 #endif
2776         }
2777 
_DeregisterCancellationConcurrency_winrt::details::_Task_impl_base2778         void _DeregisterCancellation()
2779         {
2780             if (_M_pRegistration != nullptr)
2781             {
2782                 _M_pTokenState->_DeregisterCallback(_M_pRegistration);
2783                 _M_pRegistration->_Release();
2784                 _M_pRegistration = nullptr;
2785             }
2786         }
2787 #if _MSC_VER < 1800
_CancelViaTokenConcurrency_winrt::details::_Task_impl_base2788         static void _CancelViaToken(_Task_impl_base *_PImpl)
2789         {
2790             _PImpl->_Cancel(false);
2791         }
2792 #endif
_IsCreatedConcurrency_winrt::details::_Task_impl_base2793         bool _IsCreated()
2794         {
2795             return (_M_TaskState == _Created);
2796         }
2797 
_IsStartedConcurrency_winrt::details::_Task_impl_base2798         bool _IsStarted()
2799         {
2800             return (_M_TaskState == _Started);
2801         }
2802 
_IsPendingCancelConcurrency_winrt::details::_Task_impl_base2803         bool _IsPendingCancel()
2804         {
2805             return (_M_TaskState == _PendingCancel);
2806         }
2807 
_IsCompletedConcurrency_winrt::details::_Task_impl_base2808         bool _IsCompleted()
2809         {
2810             return (_M_TaskState == _Completed);
2811         }
2812 
_IsCanceledConcurrency_winrt::details::_Task_impl_base2813         bool _IsCanceled()
2814         {
2815             return (_M_TaskState == _Canceled);
2816         }
2817 
_HasUserExceptionConcurrency_winrt::details::_Task_impl_base2818         bool _HasUserException()
2819         {
2820             return static_cast<bool>(_M_exceptionHolder);
2821         }
2822 #if _MSC_VER < 1800
_SetScheduledEventConcurrency_winrt::details::_Task_impl_base2823         void _SetScheduledEvent()
2824         {
2825             _M_Scheduled.set();
2826         }
2827 #endif
_GetExceptionHolderConcurrency_winrt::details::_Task_impl_base2828         const std::shared_ptr<_ExceptionHolder>& _GetExceptionHolder()
2829         {
2830             _CONCRT_ASSERT(_HasUserException());
2831             return _M_exceptionHolder;
2832         }
2833 
_IsApartmentAwareConcurrency_winrt::details::_Task_impl_base2834         bool _IsApartmentAware()
2835         {
2836             return _M_fFromAsync;
2837         }
2838 
_SetAsyncConcurrency_winrt::details::_Task_impl_base2839         void _SetAsync(bool _Async = true)
2840         {
2841             _M_fFromAsync = _Async;
2842         }
2843 #if _MSC_VER >= 1800
_GetTaskCreationCallstackConcurrency_winrt::details::_Task_impl_base2844         _TaskCreationCallstack _GetTaskCreationCallstack()
2845         {
2846             return _M_pTaskCreationCallstack;
2847         }
2848 
_SetTaskCreationCallstackConcurrency_winrt::details::_Task_impl_base2849         void _SetTaskCreationCallstack(const _TaskCreationCallstack &_Callstack)
2850         {
2851             _M_pTaskCreationCallstack = _Callstack;
2852         }
2853 #else
_GetTaskCreationAddressHintConcurrency_winrt::details::_Task_impl_base2854         void* _GetTaskCreationAddressHint()
2855         {
2856             return _M_pTaskCreationAddressHint;
2857         }
2858 
_SetTaskCreationAddressHintConcurrency_winrt::details::_Task_impl_base2859         void _SetTaskCreationAddressHint(void* _AddressHint)
2860         {
2861             _M_pTaskCreationAddressHint = _AddressHint;
2862         }
2863 #endif
2864         /// <summary>
2865         ///     Helper function to schedule the task on the Task Collection.
2866         /// </summary>
2867         /// <param name="_PTaskHandle">
2868         ///     The task chore handle that need to be executed.
2869         /// </param>
2870         /// <param name="_InliningMode">
2871         ///     The inlining scheduling policy for current _PTaskHandle.
2872         /// </param>
_ScheduleTaskConcurrency_winrt::details::_Task_impl_base2873         void _ScheduleTask(_UnrealizedChore * _PTaskHandle, _TaskInliningMode _InliningMode)
2874         {
2875 #if _MSC_VER < 1800
2876             // Construct the task collection; We use none token to provent it becoming interruption point.
2877             _M_pTaskCollection = Concurrency::details::_AsyncTaskCollection::_NewCollection(Concurrency::details::_CancellationTokenState::_None());
2878             // _M_pTaskCollection->_ScheduleWithAutoInline will schedule the chore onto AsyncTaskCollection with automatic inlining, in a way that honors cancellation etc.
2879 #endif
2880             try
2881             {
2882 #if _MSC_VER >= 1800
2883                 _M_TaskCollection._ScheduleTask(_PTaskHandle, _InliningMode);
2884 #else
2885                 // Do not need to check its returning state, more details please refer to _Wait method.
2886                 _M_pTaskCollection->_ScheduleWithAutoInline(_PTaskHandle, _InliningMode);
2887 #endif
2888             }
2889             catch (const Concurrency::task_canceled &)
2890             {
2891                 // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
2892                 // must be called from code that is executed within the task (throwing it from parallel work created by and waited
2893                 // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
2894                 // the exception and canceled the task. Swallow the exception here.
2895                 _CONCRT_ASSERT(_IsCanceled());
2896             }
2897             catch (const Concurrency::details::_Interruption_exception &)
2898             {
2899                 // The _TaskCollection will never be an interruption point since it has a none token.
2900                 _CONCRT_ASSERT(false);
2901             }
2902             catch (...)
2903             {
2904                 // This exception could only have come from within the chore body. It should've been caught
2905                 // and the task should be canceled with exception. Swallow the exception here.
2906                 _CONCRT_ASSERT(_HasUserException());
2907             }
2908 #if _MSC_VER < 1800
2909             // Set the event in case anyone is waiting to notify that this task has been scheduled. In the case where we
2910             // execute the chore inline, the event should be set after the chore has executed, to prevent a different thread
2911             // performing a wait on the task from waiting on the task collection before the chore is actually added to it,
2912             // and thereby returning from the wait() before the chore has executed.
2913             _SetScheduledEvent();
2914 #endif
2915         }
2916 
2917         /// <summary>
2918         ///     Function executes a continuation. This function is recorded by a parent task implementation
2919         ///     when a continuation is created in order to execute later.
2920         /// </summary>
2921         /// <param name="_PTaskHandle">
2922         ///     The continuation task chore handle that need to be executed.
2923         /// </param>
2924         /**/
_RunContinuationConcurrency_winrt::details::_Task_impl_base2925         void _RunContinuation(_ContinuationTaskHandleBase * _PTaskHandle)
2926         {
2927             _Task_ptr_base _ImplBase = _PTaskHandle->_GetTaskImplBase();
2928             if (_IsCanceled() && !_PTaskHandle->_M_isTaskBasedContinuation)
2929             {
2930                 if (_HasUserException())
2931                 {
2932                     // If the ancestor encountered an exception, transfer the exception to the continuation
2933                     // This traverses down the tree to propagate the exception.
2934                     _ImplBase->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
2935                 }
2936                 else
2937                 {
2938                     // If the ancestor was canceled, then your own execution should be canceled.
2939                     // This traverses down the tree to cancel it.
2940                     _ImplBase->_Cancel(true);
2941                 }
2942             }
2943             else
2944             {
2945                 // This can only run when the ancestor has completed or it's a task based continuation that fires when a task is canceled
2946                 // (with or without a user exception).
2947                 _CONCRT_ASSERT(_IsCompleted() || _PTaskHandle->_M_isTaskBasedContinuation);
2948 
2949 #if _MSC_VER >= 1800
2950                 _CONCRT_ASSERT(!_ImplBase->_IsCanceled());
2951                 return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
2952 #else
2953                 // If it has been canceled here (before starting), do nothing. The guy firing cancel will do the clean up.
2954                 if (!_ImplBase->_IsCanceled())
2955                 {
2956                     return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
2957                 }
2958 #endif
2959             }
2960 
2961             // If the handle is not scheduled, we need to manually delete it.
2962             delete _PTaskHandle;
2963         }
2964 
2965         // Schedule a continuation to run
_ScheduleContinuationTaskConcurrency_winrt::details::_Task_impl_base2966         void _ScheduleContinuationTask(_ContinuationTaskHandleBase * _PTaskHandle)
2967         {
2968 #if _MSC_VER >= 1800
2969             _M_taskEventLogger._LogScheduleTask(true);
2970 #endif
2971             // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a different Windows Runtime apartment)
2972             if (_PTaskHandle->_M_continuationContext._HasCapturedContext())
2973             {
2974                 // For those continuations need to be scheduled inside captured context, we will try to apply automatic inlining to their inline modes,
2975                 // if they haven't been specified as _ForceInline yet. This change will encourage those continuations to be executed inline so that reduce
2976                 // the cost of marshaling.
2977                 // For normal continuations we won't do any change here, and their inline policies are completely decided by ._ThenImpl method.
2978                 if (_PTaskHandle->_M_inliningMode != Concurrency::details::_ForceInline)
2979                 {
2980                     _PTaskHandle->_M_inliningMode = Concurrency::details::_DefaultAutoInline;
2981                 }
2982                 details::_ScheduleFuncWithAutoInline([_PTaskHandle]() -> HRESULT {
2983                     // Note that we cannot directly capture "this" pointer, instead, we should use _TaskImplPtr, a shared_ptr to the _Task_impl_base.
2984                     // Because "this" pointer will be invalid as soon as _PTaskHandle get deleted. _PTaskHandle will be deleted after being scheduled.
2985                     auto _TaskImplPtr = _PTaskHandle->_GetTaskImplBase();
2986                     if (details::_ContextCallback::_CaptureCurrent() == _PTaskHandle->_M_continuationContext)
2987                     {
2988                         _TaskImplPtr->_ScheduleTask(_PTaskHandle, Concurrency::details::_ForceInline);
2989                     }
2990                     else
2991                     {
2992                         //
2993                         // It's entirely possible that the attempt to marshal the call into a differing context will fail. In this case, we need to handle
2994                         // the exception and mark the continuation as canceled with the appropriate exception. There is one slight hitch to this:
2995                         //
2996                         // NOTE: COM's legacy behavior is to swallow SEH exceptions and marshal them back as HRESULTS. This will in effect turn an SEH into
2997                         // a C++ exception that gets tagged on the task. One unfortunate result of this is that various pieces of the task infrastructure will
2998                         // not be in a valid state after this in /EHsc (due to the lack of destructors running, etc...).
2999                         //
3000                         try
3001                         {
3002                             // Dev10 compiler needs this!
3003                             auto _PTaskHandle1 = _PTaskHandle;
3004                             _PTaskHandle->_M_continuationContext._CallInContext([_PTaskHandle1, _TaskImplPtr]() -> HRESULT {
3005                                 _TaskImplPtr->_ScheduleTask(_PTaskHandle1, Concurrency::details::_ForceInline);
3006                                 return S_OK;
3007                             });
3008                         }
3009                         catch (IRestrictedErrorInfo*& _E)
3010                         {
3011                             _TaskImplPtr->_CancelWithException(_E);
3012                         }
3013                         catch (...)
3014                         {
3015                             _TaskImplPtr->_CancelWithException(std::current_exception());
3016                         }
3017                     }
3018                     return S_OK;
3019                 }, _PTaskHandle->_M_inliningMode);
3020             }
3021             else
3022             {
3023                 _ScheduleTask(_PTaskHandle, _PTaskHandle->_M_inliningMode);
3024             }
3025         }
3026 
3027         /// <summary>
3028         ///     Schedule the actual continuation. This will either schedule the function on the continuation task's implementation
3029         ///     if the task has completed or append it to a list of functions to execute when the task actually does complete.
3030         /// </summary>
3031         /// <typeparam name="_FuncInputType">
3032         ///     The input type of the task.
3033         /// </typeparam>
3034         /// <typeparam name="_FuncOutputType">
3035         ///     The output type of the task.
3036         /// </typeparam>
3037         /**/
_ScheduleContinuationConcurrency_winrt::details::_Task_impl_base3038         void _ScheduleContinuation(_ContinuationTaskHandleBase * _PTaskHandle)
3039         {
3040             enum { _Nothing, _Schedule, _Cancel, _CancelWithException } _Do = _Nothing;
3041 
3042             // If the task has canceled, cancel the continuation. If the task has completed, execute the continuation right away.
3043             // Otherwise, add it to the list of pending continuations
3044             {
3045                 scoped_lock _LockHolder(_M_ContinuationsCritSec);
3046                 if (_IsCompleted() || (_IsCanceled() && _PTaskHandle->_M_isTaskBasedContinuation))
3047                 {
3048                     _Do = _Schedule;
3049                 }
3050                 else if (_IsCanceled())
3051                 {
3052                     if (_HasUserException())
3053                     {
3054                         _Do = _CancelWithException;
3055                     }
3056                     else
3057                     {
3058                         _Do = _Cancel;
3059                     }
3060                 }
3061                 else
3062                 {
3063                     // chain itself on the continuation chain.
3064                     _PTaskHandle->_M_next = _M_Continuations;
3065                     _M_Continuations = _PTaskHandle;
3066                 }
3067             }
3068 
3069             // Cancellation and execution of continuations should be performed after releasing the lock. Continuations off of
3070             // async tasks may execute inline.
3071             switch (_Do)
3072             {
3073             case _Schedule:
3074             {
3075                               _PTaskHandle->_GetTaskImplBase()->_ScheduleContinuationTask(_PTaskHandle);
3076                               break;
3077             }
3078             case _Cancel:
3079             {
3080                             // If the ancestor was canceled, then your own execution should be canceled.
3081                             // This traverses down the tree to cancel it.
3082                             _PTaskHandle->_GetTaskImplBase()->_Cancel(true);
3083 
3084                             delete _PTaskHandle;
3085                             break;
3086             }
3087             case _CancelWithException:
3088             {
3089                                          // If the ancestor encountered an exception, transfer the exception to the continuation
3090                                          // This traverses down the tree to propagate the exception.
3091                                          _PTaskHandle->_GetTaskImplBase()->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
3092 
3093                                          delete _PTaskHandle;
3094                                          break;
3095             }
3096             case _Nothing:
3097             default:
3098                 // In this case, we have inserted continuation to continuation chain,
3099                 // nothing more need to be done, just leave.
3100                 break;
3101             }
3102         }
3103 
_RunTaskContinuationsConcurrency_winrt::details::_Task_impl_base3104         void _RunTaskContinuations()
3105         {
3106             // The link list can no longer be modified at this point,
3107             // since all following up continuations will be scheduled by themselves.
3108             _ContinuationList _Cur = _M_Continuations, _Next;
3109             _M_Continuations = nullptr;
3110             while (_Cur)
3111             {
3112                 // Current node might be deleted after running,
3113                 // so we must fetch the next first.
3114                 _Next = _Cur->_M_next;
3115                 _RunContinuation(_Cur);
3116                 _Cur = _Next;
3117             }
3118         }
_IsNonBlockingThreadConcurrency_winrt::details::_Task_impl_base3119         static bool  _IsNonBlockingThread()
3120         {
3121             APTTYPE _AptType;
3122             APTTYPEQUALIFIER _AptTypeQualifier;
3123 
3124             HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
3125             //
3126             // If it failed, it's not a Windows Runtime/COM initialized thread. This is not a failure.
3127             //
3128             if (SUCCEEDED(hr))
3129             {
3130                 switch (_AptType)
3131                 {
3132                 case APTTYPE_STA:
3133                 case APTTYPE_MAINSTA:
3134                     return true;
3135                     break;
3136                 case APTTYPE_NA:
3137                     switch (_AptTypeQualifier)
3138                     {
3139                         // A thread executing in a neutral apartment is either STA or MTA. To find out if this thread is allowed
3140                         // to wait, we check the app qualifier. If it is an STA thread executing in a neutral apartment, waiting
3141                         // is illegal, because the thread is responsible for pumping messages and waiting on a task could take the
3142                         // thread out of circulation for a while.
3143                     case APTTYPEQUALIFIER_NA_ON_STA:
3144                     case APTTYPEQUALIFIER_NA_ON_MAINSTA:
3145                         return true;
3146                         break;
3147                     }
3148                     break;
3149                 }
3150             }
3151 #if _UITHREADCTXT_SUPPORT
3152             // This method is used to throw an exepection in _Wait() if called within STA.  We
3153             // want the same behavior if _Wait is called on the UI thread.
3154             if (SUCCEEDED(CaptureUiThreadContext(nullptr)))
3155             {
3156                 return true;
3157             }
3158 #endif // _UITHREADCTXT_SUPPORT
3159 
3160             return false;
3161         }
3162 
3163         template<typename _ReturnType, typename _Result, typename _OpType, typename _CompHandlerType, typename _ResultType>
_AsyncInitConcurrency_winrt::details::_Task_impl_base3164         static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type & _OuterTask,
3165             _AsyncInfoImpl<_OpType, _CompHandlerType, _ResultType>* _AsyncOp)
3166         {
3167             typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_GetUnwrappedType(stdx::declval<_OpType*>()))>::type _Result_abi;
3168             // This method is invoked either when a task is created from an existing async operation or
3169             // when a lambda that creates an async operation executes.
3170 
3171             // If the outer task is pending cancel, cancel the async operation before setting the completed handler. The COM reference on
3172             // the IAsyncInfo object will be released when all *references to the operation go out of scope.
3173 
3174             // This assertion uses the existence of taskcollection to determine if the task was created from an event.
3175             // That is no longer valid as even tasks created from a user lambda could have no underlying taskcollection
3176             // when a custom scheduler is used.
3177 #if _MSC_VER < 1800
3178             _CONCRT_ASSERT(((_OuterTask->_M_pTaskCollection == nullptr) || _OuterTask->_M_fUnwrappedTask) && !_OuterTask->_IsCanceled());
3179 #endif
3180 
3181             // Pass the shared_ptr by value into the lambda instead of using 'this'.
3182 
3183             _AsyncOp->put_Completed(Microsoft::WRL::Callback<_CompHandlerType>(
3184                 [_OuterTask, _AsyncOp](_OpType* _Operation, ABI::Windows::Foundation::AsyncStatus _Status) mutable -> HRESULT
3185             {
3186                 HRESULT hr = S_OK;
3187                 if (_Status == ABI::Windows::Foundation::AsyncStatus::Canceled)
3188                 {
3189                     _OuterTask->_Cancel(true);
3190                 }
3191                 else if (_Status == ABI::Windows::Foundation::AsyncStatus::Error)
3192                 {
3193                     HRESULT _hr;
3194                     Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> pAsyncInfo;
3195                     if (SUCCEEDED(hr = _Operation->QueryInterface<ABI::Windows::Foundation::IAsyncInfo>(pAsyncInfo.GetAddressOf())) && SUCCEEDED(hr = pAsyncInfo->get_ErrorCode(&_hr)))
3196                         _OuterTask->_CancelWithException(std::make_exception_ptr(_hr));
3197                 }
3198                 else
3199                 {
3200                     _CONCRT_ASSERT(_Status == ABI::Windows::Foundation::AsyncStatus::Completed);
3201                     _NormalizeVoidToUnitType<_Result_abi>::_Type results;
3202                     if (SUCCEEDED(hr = _AsyncOp->GetResults(&results)))
3203                         _OuterTask->_FinalizeAndRunContinuations(results);
3204                 }
3205                 // Take away this shared pointers reference on the task instead of waiting for the delegate to be released. It could
3206                 // be released on a different thread after a delay, and not releasing the reference here could cause the tasks to hold
3207                 // on to resources longer than they should. As an example, without this reset, writing to a file followed by reading from
3208                 // it using the Windows Runtime Async APIs causes a sharing violation.
3209                 // Using const_cast is the workaround for failed mutable keywords
3210                 const_cast<_Task_ptr<_ReturnType>::_Type &>(_OuterTask).reset();
3211                 return hr;
3212             }).Get());
3213             _OuterTask->_SetUnwrappedAsyncOp(_AsyncOp);
3214         }
3215         template<typename _ReturnType, typename _InternalReturnType>
_AsyncInitConcurrency_winrt::details::_Task_impl_base3216         static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type& _OuterTask, const task<_InternalReturnType> & _UnwrappedTask)
3217         {
3218             _CONCRT_ASSERT(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled());
3219             //
3220             // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in the
3221             // presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception handling continuation
3222             // off the inner task which does the appropriate funnelling to the outer one. We use _Then instead of then to prevent
3223             // the exception from being marked as observed by our internal continuation. This continuation must be scheduled regardless
3224             // of whether or not the _OuterTask task is canceled.
3225             //
3226             _UnwrappedTask._Then([_OuterTask](task<_InternalReturnType> _AncestorTask) -> HRESULT {
3227 
3228                 if (_AncestorTask._GetImpl()->_IsCompleted())
3229                 {
3230                     _OuterTask->_FinalizeAndRunContinuations(_AncestorTask._GetImpl()->_GetResult());
3231                 }
3232                 else
3233                 {
3234                     _CONCRT_ASSERT(_AncestorTask._GetImpl()->_IsCanceled());
3235                     if (_AncestorTask._GetImpl()->_HasUserException())
3236                     {
3237                         // Set _PropagatedFromAncestor to false, since _AncestorTask is not an ancestor of _UnwrappedTask.
3238                         // Instead, it is the enclosing task.
3239                         _OuterTask->_CancelWithExceptionHolder(_AncestorTask._GetImpl()->_GetExceptionHolder(), false);
3240                     }
3241                     else
3242                     {
3243                         _OuterTask->_Cancel(true);
3244                     }
3245                 }
3246                 return S_OK;
3247 #if _MSC_VER >= 1800
3248             }, nullptr, Concurrency::details::_DefaultAutoInline);
3249 #else
3250             }, nullptr, false, Concurrency::details::_DefaultAutoInline);
3251 #endif
3252         }
3253 
3254 #if _MSC_VER >= 1800
3255         Concurrency::scheduler_ptr _GetScheduler() const
3256         {
3257             return _M_TaskCollection._GetScheduler();
3258         }
3259 #else
3260         Concurrency::event _M_Completed;
3261         Concurrency::event _M_Scheduled;
3262 #endif
3263 
3264         // Tracks the internal state of the task
3265         volatile _TaskInternalState _M_TaskState;
3266         // Set to true either if the ancestor task had the flag set to true, or if the lambda that does the work of this task returns an
3267         // async operation or async action that is unwrapped by the runtime.
3268         bool _M_fFromAsync;
3269 #if _MSC_VER < 1800
3270         // Set to true if we need to marshal the inner parts of an aggregate type like std::vector<T^> or std::pair<T^, size_t>. We only marshal
3271         // the contained T^s if we create the vector or pair, such as on a when_any or a when_all operation.
3272         bool _M_fRuntimeAggregate;
3273 #endif
3274         // Set to true when a continuation unwraps a task or async operation.
3275         bool _M_fUnwrappedTask;
3276 
3277         // An exception thrown by the task body is captured in an exception holder and it is shared with all value based continuations rooted at the task.
3278         // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
3279         // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
3280         std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
3281 
3282         typedef _ContinuationTaskHandleBase * _ContinuationList;
3283 
3284         critical_section _M_ContinuationsCritSec;
3285         _ContinuationList _M_Continuations;
3286 
3287         // The cancellation token state.
3288         Concurrency::details::_CancellationTokenState * _M_pTokenState;
3289 
3290         // The registration on the token.
3291         Concurrency::details::_CancellationTokenRegistration * _M_pRegistration;
3292 
3293         // The async task collection wrapper
3294 #if _MSC_VER >= 1800
3295         Concurrency::details::_TaskCollection_t _M_TaskCollection;
3296 
3297         // Callstack for function call (constructor or .then) that created this task impl.
3298         _TaskCreationCallstack _M_pTaskCreationCallstack;
3299 
3300         _TaskEventLogger _M_taskEventLogger;
3301 #else
3302         Concurrency::details::_AsyncTaskCollection * _M_pTaskCollection;
3303 
3304         // Points to the source code instruction right after the function call (constructor or .then) that created this task impl.
3305         void* _M_pTaskCreationAddressHint;
3306 #endif
3307 
3308     private:
3309         // Must not be copied by value:
3310         _Task_impl_base(const _Task_impl_base&);
3311         _Task_impl_base const & operator=(_Task_impl_base const&);
3312     };
3313 
3314 #if _MSC_VER >= 1800
3315 #if _PPLTASK_ASYNC_LOGGING
3316     inline void _TaskEventLogger::_LogTaskCompleted()
3317     {
3318         if (_M_scheduled)
3319         {
3320             ::Windows::Foundation::AsyncStatus _State;
3321             if (_M_task->_IsCompleted())
3322                 _State = ::Windows::Foundation::AsyncStatus::Completed;
3323             else if (_M_task->_HasUserException())
3324                 _State = ::Windows::Foundation::AsyncStatus::Error;
3325             else
3326                 _State = ::Windows::Foundation::AsyncStatus::Canceled;
3327 
3328             if (details::_IsCausalitySupported())
3329             {
3330                 ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
3331                     _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), _State);
3332             }
3333         }
3334     }
3335 #endif
3336 #endif
3337 
3338     template<typename _ReturnType>
3339     struct _Task_impl : public _Task_impl_base
3340     {
3341         typedef ABI::Windows::Foundation::IAsyncInfo _AsyncOperationType;
3342 #if _MSC_VER >= 1800
3343         _Task_impl(Concurrency::details::_CancellationTokenState * _Ct, Concurrency::scheduler_ptr _Scheduler_arg)
3344             : _Task_impl_base(_Ct, _Scheduler_arg)
3345 #else
3346         _Task_impl(Concurrency::details::_CancellationTokenState * _Ct) : _Task_impl_base(_Ct)
3347 #endif
3348         {
3349             _M_unwrapped_async_op = nullptr;
3350         }
3351         virtual ~_Task_impl()
3352         {
3353             // We must invoke _DeregisterCancellation in the derived class destructor. Calling it in the base class destructor could cause
3354             // a partially initialized _Task_impl to be in the list of registrations for a cancellation token.
3355             _DeregisterCancellation();
3356         }
3357         virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder> & _ExceptionHolder)
3358         {
3359             enum { _Nothing, _RunContinuations, _Cancel } _Do = _Nothing;
3360             {
3361                 scoped_lock _LockHolder(_M_ContinuationsCritSec);
3362                 if (_UserException)
3363                 {
3364                     _CONCRT_ASSERT(_SynchronousCancel && !_IsCompleted());
3365                     // If the state is _Canceled, the exception has to be coming from an ancestor.
3366                     _CONCRT_ASSERT(!_IsCanceled() || _PropagatedFromAncestor);
3367 #if _MSC_VER < 1800
3368                     // If the state is _Started or _PendingCancel, the exception cannot be coming from an ancestor.
3369                     _CONCRT_ASSERT((!_IsStarted() && !_IsPendingCancel()) || !_PropagatedFromAncestor);
3370 #endif
3371                     // We should not be canceled with an exception more than once.
3372                     _CONCRT_ASSERT(!_HasUserException());
3373 
3374                     if (_M_TaskState == _Canceled)
3375                     {
3376                         // If the task has finished cancelling there should not be any continuation records in the array.
3377                         return false;
3378                     }
3379                     else
3380                     {
3381                         _CONCRT_ASSERT(_M_TaskState != _Completed);
3382                         _M_exceptionHolder = _ExceptionHolder;
3383                     }
3384                 }
3385                 else
3386                 {
3387                     // Completed is a non-cancellable state, and if this is an asynchronous cancel, we're unable to do better than the last async cancel
3388                     // which is to say, cancellation is already initiated, so return early.
3389                     if (_IsCompleted() || _IsCanceled() || (_IsPendingCancel() && !_SynchronousCancel))
3390                     {
3391                         _CONCRT_ASSERT(!_IsCompleted() || !_HasUserException());
3392                         return false;
3393                     }
3394                     _CONCRT_ASSERT(!_SynchronousCancel || !_HasUserException());
3395                 }
3396 
3397 #if _MSC_VER >= 1800
3398                 if (_SynchronousCancel)
3399 #else
3400                 if (_SynchronousCancel || _IsCreated())
3401 #endif
3402                 {
3403                     // Be aware that this set must be done BEFORE _M_Scheduled being set, or race will happen between this and wait()
3404                     _M_TaskState = _Canceled;
3405 #if _MSC_VER < 1800
3406                     _M_Scheduled.set();
3407 #endif
3408 
3409                     // Cancellation completes the task, so all dependent tasks must be run to cancel them
3410                     // They are canceled when they begin running (see _RunContinuation) and see that their
3411                     // ancestor has been canceled.
3412                     _Do = _RunContinuations;
3413                 }
3414                 else
3415                 {
3416 #if _MSC_VER >= 1800
3417                     _CONCRT_ASSERT(!_UserException);
3418 
3419                     if (_IsStarted())
3420                     {
3421                         // should not initiate cancellation under a lock
3422                         _Do = _Cancel;
3423                     }
3424 
3425                     // The _M_TaskState variable transitions to _Canceled when cancellation is completed (the task is not executing user code anymore).
3426                     // In the case of a synchronous cancel, this can happen immediately, whereas with an asynchronous cancel, the task has to move from
3427                     // _Started to _PendingCancel before it can move to _Canceled when it is finished executing.
3428                     _M_TaskState = _PendingCancel;
3429 
3430                     _M_taskEventLogger._LogCancelTask();
3431                 }
3432             }
3433 
3434             switch (_Do)
3435             {
3436             case _Cancel:
3437             {
3438 #else
3439                     _CONCRT_ASSERT(_IsStarted() && !_UserException);
3440 #endif
3441                     // The _M_TaskState variable transitions to _Canceled when cancellation is completed (the task is not executing user code anymore).
3442                     // In the case of a synchronous cancel, this can happen immediately, whereas with an asynchronous cancel, the task has to move from
3443                     // _Started to _PendingCancel before it can move to _Canceled when it is finished executing.
3444                     _M_TaskState = _PendingCancel;
3445                     if (_M_unwrapped_async_op != nullptr)
3446                     {
3447                         // We will only try to cancel async operation but not unwrapped tasks, since unwrapped tasks cannot be canceled without its token.
3448                         if (_M_unwrapped_async_op)    _M_unwrapped_async_op->Cancel();
3449                     }
3450 #if _MSC_VER >= 1800
3451                         _M_TaskCollection._Cancel();
3452                         break;
3453 #else
3454                 // Optimistic trying for cancelation
3455                 if (_M_pTaskCollection != nullptr)
3456                 {
3457                     _M_pTaskCollection->_Cancel();
3458                 }
3459 #endif
3460                 }
3461 #if _MSC_VER < 1800
3462             }
3463 #endif
3464 
3465             // Only execute continuations and mark the task as completed if we were able to move the task to the _Canceled state.
3466 #if _MSC_VER >= 1800
3467             case _RunContinuations:
3468             {
3469                 _M_TaskCollection._Complete();
3470 #else
3471             if (_RunContinuations)
3472             {
3473                 _M_Completed.set();
3474 #endif
3475 
3476                 if (_M_Continuations)
3477                 {
3478                     // Scheduling cancellation with automatic inlining.
3479                     details::_ScheduleFuncWithAutoInline([=]() -> HRESULT { _RunTaskContinuations(); return S_OK; }, Concurrency::details::_DefaultAutoInline);
3480                 }
3481 #if _MSC_VER >= 1800
3482                 break;
3483             }
3484 #endif
3485             }
3486             return true;
3487         }
3488         void _FinalizeAndRunContinuations(_ReturnType _Result)
3489         {
3490 
3491 #if _MSC_VER >= 1800
3492             _M_Result.Set(_Result);
3493 #else
3494             _M_Result = _Result;
3495             _M_ResultContext = _ResultContext<_ReturnType>::_GetContext(_M_fRuntimeAggregate);
3496 #endif
3497             {
3498                 //
3499                 // Hold this lock to ensure continuations being concurrently either get added
3500                 // to the _M_Continuations vector or wait for the result
3501                 //
3502                 scoped_lock _LockHolder(_M_ContinuationsCritSec);
3503 
3504                 // A task could still be in the _Created state if it was created with a task_completion_event.
3505                 // It could also be in the _Canceled state for the same reason.
3506                 _CONCRT_ASSERT(!_HasUserException() && !_IsCompleted());
3507                 if (_IsCanceled())
3508                 {
3509                     return;
3510                 }
3511 
3512                 // Always transition to "completed" state, even in the face of unacknowledged pending cancellation
3513                 _M_TaskState = _Completed;
3514             }
3515 #if _MSC_VER >= 1800
3516             _M_TaskCollection._Complete();
3517 #else
3518             _M_Completed.set();
3519 #endif
3520             _RunTaskContinuations();
3521         }
3522         //
3523         // This method is invoked when the starts executing. The task returns early if this method returns true.
3524         //
3525         bool _TransitionedToStarted()
3526         {
3527             scoped_lock _LockHolder(_M_ContinuationsCritSec);
3528 #if _MSC_VER >= 1800
3529             // Canceled state could only result from antecedent task's canceled state, but that code path will not reach here.
3530             _ASSERT(!_IsCanceled());
3531             if (_IsPendingCancel())
3532 #else
3533             if (_IsCanceled())
3534 #endif
3535             {
3536                 return false;
3537             }
3538             _CONCRT_ASSERT(_IsCreated());
3539             _M_TaskState = _Started;
3540             return true;
3541         }
3542         void _SetUnwrappedAsyncOp(_AsyncOperationType* _AsyncOp)
3543         {
3544             scoped_lock _LockHolder(_M_ContinuationsCritSec);
3545             // Cancel the async operation if the task itself is canceled, since the thread that canceled the task missed it.
3546             if (_IsPendingCancel())
3547             {
3548                 _CONCRT_ASSERT(!_IsCanceled());
3549                 if (_AsyncOp) _AsyncOp->Cancel();
3550             }
3551             else
3552             {
3553                 _M_unwrapped_async_op = _AsyncOp;
3554             }
3555         }
3556 #if _MSC_VER >= 1800
3557         // Return true if the task has reached a terminal state
3558         bool _IsDone()
3559         {
3560             return _IsCompleted() || _IsCanceled();
3561         }
3562 #endif
3563         _ReturnType _GetResult()
3564         {
3565 #if _MSC_VER >= 1800
3566             return _M_Result.Get();
3567 #else
3568             return _ResultContext<_ReturnType>::_GetValue(_M_Result, _M_ResultContext, _M_fRuntimeAggregate);
3569 #endif
3570         }
3571 #if _MSC_VER >= 1800
3572         _ResultHolder<_ReturnType>                 _M_Result;        // this means that the result type must have a public default ctor.
3573 #else
3574         _ReturnType                                 _M_Result;        // this means that the result type must have a public default ctor.
3575 #endif
3576         Microsoft::WRL::ComPtr<_AsyncOperationType> _M_unwrapped_async_op;
3577 #if _MSC_VER < 1800
3578         _ContextCallback                            _M_ResultContext;
3579 #endif
3580     };
3581 
3582     template<typename _ResultType>
3583     struct _Task_completion_event_impl
3584     {
3585 #if _MSC_VER >= 1800
3586     private:
3587         _Task_completion_event_impl(const _Task_completion_event_impl&);
3588         _Task_completion_event_impl& operator=(const _Task_completion_event_impl&);
3589 
3590     public:
3591 #endif
3592         typedef std::vector<typename _Task_ptr<_ResultType>::_Type> _TaskList;
3593 
3594         _Task_completion_event_impl() : _M_fHasValue(false), _M_fIsCanceled(false)
3595         {
3596         }
3597 
3598         bool _HasUserException()
3599         {
3600             return _M_exceptionHolder != nullptr;
3601         }
3602 
3603         ~_Task_completion_event_impl()
3604         {
3605             for (auto _TaskIt = _M_tasks.begin(); _TaskIt != _M_tasks.end(); ++_TaskIt)
3606             {
3607                 _CONCRT_ASSERT(!_M_fHasValue && !_M_fIsCanceled);
3608                 // Cancel the tasks since the event was never signaled or canceled.
3609                 (*_TaskIt)->_Cancel(true);
3610             }
3611         }
3612 
3613         // We need to protect the loop over the array, so concurrent_vector would not have helped
3614         _TaskList                           _M_tasks;
3615         critical_section                    _M_taskListCritSec;
3616 #if _MSC_VER >= 1800
3617         _ResultHolder<_ResultType>         _M_value;
3618 #else
3619         _ResultType                         _M_value;
3620 #endif
3621         std::shared_ptr<_ExceptionHolder>   _M_exceptionHolder;
3622         bool                                _M_fHasValue;
3623         bool                                _M_fIsCanceled;
3624     };
3625 
3626     // Utility method for dealing with void functions
3627     inline std::function<HRESULT(_Unit_type*)> _MakeVoidToUnitFunc(const std::function<HRESULT(void)>& _Func)
3628     {
3629         return [=](_Unit_type* retVal) -> HRESULT { HRESULT hr = _Func(); *retVal = _Unit_type(); return hr; };
3630     }
3631 
3632     template <typename _Type>
3633     std::function<HRESULT(_Unit_type, _Type*)> _MakeUnitToTFunc(const std::function<HRESULT(_Type*)>& _Func)
3634     {
3635         return [=](_Unit_type, _Type* retVal) -> HRESULT { HRESULT hr = _Func(retVal); return hr;  };
3636     }
3637 
3638     template <typename _Type>
3639     std::function<HRESULT(_Type, _Unit_type*)> _MakeTToUnitFunc(const std::function<HRESULT(_Type)>& _Func)
3640     {
3641         return[=](_Type t, _Unit_type* retVal) -> HRESULT { HRESULT hr = _Func(t); *retVal = _Unit_type(); return hr;  };
3642     }
3643 
3644     inline std::function<HRESULT(_Unit_type, _Unit_type*)> _MakeUnitToUnitFunc(const std::function<HRESULT(void)>& _Func)
3645     {
3646         return [=](_Unit_type, _Unit_type* retVal) -> HRESULT { HRESULT hr = _Func(); *retVal = _Unit_type(); return hr;  };
3647     }
3648 }
3649 
3650 
3651 /// <summary>
3652 ///     The <c>task_completion_event</c> class allows you to delay the execution of a task until a condition is satisfied,
3653 ///     or start a task in response to an external event.
3654 /// </summary>
3655 /// <typeparam name="_ResultType">
3656 ///     The result type of this <c>task_completion_event</c> class.
3657 /// </typeparam>
3658 /// <remarks>
3659 ///     Use a task created from a task completion event when your scenario requires you to create a task that will complete, and
3660 ///     thereby have its continuations scheduled for execution, at some point in the future. The <c>task_completion_event</c> must
3661 ///     have the same type as the task you create, and calling the set method on the task completion event with a value of that type
3662 ///     will cause the associated task to complete, and provide that value as a result to its continuations.
3663 ///     <para>If the task completion event is never signaled, any tasks created from it will be canceled when it is destructed.</para>
3664 ///     <para><c>task_completion_event</c> behaves like a smart pointer, and should be passed by value.</para>
3665 /// </remarks>
3666 /// <seealso cref="task Class"/>
3667 /**/
3668 template<typename _ResultType>
3669 class task_completion_event
3670 {
3671 public:
3672     /// <summary>
3673     ///     Constructs a <c>task_completion_event</c> object.
3674     /// </summary>
3675     /**/
3676     task_completion_event() : _M_Impl(std::make_shared<details::_Task_completion_event_impl<_ResultType>>())
3677     {
3678     }
3679 
3680     /// <summary>
3681     ///     Sets the task completion event.
3682     /// </summary>
3683     /// <param name="_Result">
3684     ///     The result to set this event with.
3685     /// </param>
3686     /// <returns>
3687     ///     The method returns <c>true</c> if it was successful in setting the event. It returns <c>false</c> if the event is already set.
3688     /// </returns>
3689     /// <remarks>
3690     ///     In the presence of multiple or concurrent calls to <c>set</c>, only the first call will succeed and its result (if any) will be stored in the
3691     ///     task completion event. The remaining sets are ignored and the method will return false. When you set a task completion event, all the
3692     ///     tasks created from that event will immediately complete, and its continuations, if any, will be scheduled. Task completion objects that have
3693     ///     a <typeparamref name="_ResultType"/> other than <c>void</c> will pass the value <paramref value="_Result"/> to their continuations.
3694     /// </remarks>
3695     /**/
3696     bool set(_ResultType _Result) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3697     {
3698         // Subsequent sets are ignored. This makes races to set benign: the first setter wins and all others are ignored.
3699         if (_IsTriggered())
3700         {
3701             return false;
3702         }
3703 
3704         _TaskList _Tasks;
3705         bool _RunContinuations = false;
3706         {
3707             details::scoped_lock _LockHolder(_M_Impl->_M_taskListCritSec);
3708 
3709             if (!_IsTriggered())
3710             {
3711 #if _MSC_VER >= 1800
3712                 _M_Impl->_M_value.Set(_Result);
3713 #else
3714                 _M_Impl->_M_value = _Result;
3715 #endif
3716                 _M_Impl->_M_fHasValue = true;
3717 
3718                 _Tasks.swap(_M_Impl->_M_tasks);
3719                 _RunContinuations = true;
3720             }
3721         }
3722 
3723         if (_RunContinuations)
3724         {
3725             for (auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt)
3726             {
3727 #if _MSC_VER >= 1800
3728                 // If current task was cancelled by a cancellation_token, it would be in cancel pending state.
3729                 if ((*_TaskIt)->_IsPendingCancel())
3730                     (*_TaskIt)->_Cancel(true);
3731                 else
3732                 {
3733                     // Tasks created with task_completion_events can be marked as async, (we do this in when_any and when_all
3734                     // if one of the tasks involved is an async task). Since continuations of async tasks can execute inline, we
3735                     // need to run continuations after the lock is released.
3736                     (*_TaskIt)->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
3737                 }
3738 #else
3739                 // Tasks created with task_completion_events can be marked as async, (we do this in when_any and when_all
3740                 // if one of the tasks involved is an async task). Since continuations of async tasks can execute inline, we
3741                 // need to run continuations after the lock is released.
3742                 (*_TaskIt)->_FinalizeAndRunContinuations(_M_Impl->_M_value);
3743 #endif
3744             }
3745             if (_M_Impl->_HasUserException())
3746             {
3747                 _M_Impl->_M_exceptionHolder.reset();
3748             }
3749             return true;
3750         }
3751 
3752         return false;
3753     }
3754 #if _MSC_VER >= 1800
3755 
3756     template<typename _E>
3757     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
3758         bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3759     {
3760             // It is important that _CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for set_exception.
3761             return _Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
3762     }
3763 #endif
3764 
3765     /// <summary>
3766     ///     Propagates an exception to all tasks associated with this event.
3767     /// </summary>
3768     /// <param>
3769     ///     The exception_ptr that indicates the exception to set this event with.
3770     /// </param>
3771     /**/
3772     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
3773         bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3774     {
3775             // It is important that _ReturnAddress() evaluate to the instruction after the call instruction for set_exception.
3776 #if _MSC_VER >= 1800
3777             return _Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
3778 #else
3779             return _Cancel(_ExceptionPtr, _ReturnAddress());
3780 #endif
3781     }
3782 
3783     /// <summary>
3784     ///     Internal method to cancel the task_completion_event. Any task created using this event will be marked as canceled if it has
3785     ///     not already been set.
3786     /// </summary>
3787     bool _Cancel() const
3788     {
3789         // Cancel with the stored exception if one exists.
3790         return _CancelInternal();
3791     }
3792 
3793     /// <summary>
3794     ///     Internal method to cancel the task_completion_event with the exception provided. Any task created using this event will be canceled
3795     ///     with the same exception.
3796     /// </summary>
3797     template<typename _ExHolderType>
3798 #if _MSC_VER >= 1800
3799     bool _Cancel(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack()) const
3800 #else
3801     bool _Cancel(_ExHolderType _ExHolder, void* _SetExceptionAddressHint = nullptr) const
3802 #endif
3803     {
3804         (void)_SetExceptionAddressHint;
3805         bool _Canceled;
3806 #if _MSC_VER >= 1800
3807         if(_StoreException(_ExHolder, _SetExceptionAddressHint))
3808 #else
3809         if (_StoreException(_ExHolder))
3810 #endif
3811         {
3812             _Canceled = _CancelInternal();
3813             _CONCRT_ASSERT(_Canceled);
3814         }
3815         else
3816         {
3817             _Canceled = false;
3818         }
3819         return _Canceled;
3820     }
3821 
3822     /// <summary>
3823     ///     Internal method that stores an exception in the task completion event. This is used internally by when_any.
3824     ///     Note, this does not cancel the task completion event. A task completion event with a stored exception
3825     ///     can bet set() successfully. If it is canceled, it will cancel with the stored exception, if one is present.
3826     /// </summary>
3827     template<typename _ExHolderType>
3828 #if _MSC_VER >= 1800
3829     bool _StoreException(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack()) const
3830 #else
3831     bool _StoreException(_ExHolderType _ExHolder, void* _SetExceptionAddressHint = nullptr) const
3832 #endif
3833     {
3834         details::scoped_lock _LockHolder(_M_Impl->_M_taskListCritSec);
3835         if (!_IsTriggered() && !_M_Impl->_HasUserException())
3836         {
3837             // Create the exception holder only if we have ensured there we will be successful in setting it onto the
3838             // task completion event. Failing to do so will result in an unobserved task exception.
3839             _M_Impl->_M_exceptionHolder = _ToExceptionHolder(_ExHolder, _SetExceptionAddressHint);
3840             return true;
3841         }
3842         return false;
3843     }
3844 
3845     /// <summary>
3846     ///     Tests whether current event has been either Set, or Canceled.
3847     /// </summary>
3848     bool _IsTriggered() const
3849     {
3850         return _M_Impl->_M_fHasValue || _M_Impl->_M_fIsCanceled;
3851     }
3852 
3853 private:
3854 
3855 #if _MSC_VER >= 1800
3856     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder, const details::_TaskCreationCallstack&)
3857 #else
3858     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder, void*)
3859 #endif
3860     {
3861         return _ExHolder;
3862     }
3863 
3864 #if _MSC_VER >= 1800
3865     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack &_SetExceptionAddressHint)
3866 #else
3867     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(std::exception_ptr _ExceptionPtr, void* _SetExceptionAddressHint)
3868 #endif
3869     {
3870         return std::make_shared<details::_ExceptionHolder>(_ExceptionPtr, _SetExceptionAddressHint);
3871     }
3872 
3873     template <typename T> friend class task; // task can register itself with the event by calling the private _RegisterTask
3874     template <typename T> friend class task_completion_event;
3875 
3876     typedef typename details::_Task_completion_event_impl<_ResultType>::_TaskList _TaskList;
3877 
3878     /// <summary>
3879     ///    Cancels the task_completion_event.
3880     /// </summary>
3881     bool _CancelInternal() const
3882     {
3883         // Cancellation of task completion events is an internal only utility. Our usage is such that _CancelInternal
3884         // will never be invoked if the task completion event has been set.
3885         _CONCRT_ASSERT(!_M_Impl->_M_fHasValue);
3886         if (_M_Impl->_M_fIsCanceled)
3887         {
3888             return false;
3889         }
3890 
3891         _TaskList _Tasks;
3892         bool _Cancel = false;
3893         {
3894             details::scoped_lock _LockHolder(_M_Impl->_M_taskListCritSec);
3895             _CONCRT_ASSERT(!_M_Impl->_M_fHasValue);
3896             if (!_M_Impl->_M_fIsCanceled)
3897             {
3898                 _M_Impl->_M_fIsCanceled = true;
3899                 _Tasks.swap(_M_Impl->_M_tasks);
3900                 _Cancel = true;
3901             }
3902         }
3903 
3904         bool _UserException = _M_Impl->_HasUserException();
3905 
3906         if (_Cancel)
3907         {
3908             for (auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt)
3909             {
3910                 // Need to call this after the lock is released. See comments in set().
3911                 if (_UserException)
3912                 {
3913                     (*_TaskIt)->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
3914                 }
3915                 else
3916                 {
3917                     (*_TaskIt)->_Cancel(true);
3918                 }
3919             }
3920         }
3921         return _Cancel;
3922     }
3923 
3924     /// <summary>
3925     ///     Register a task with this event. This function is called when a task is constructed using
3926     ///     a task_completion_event.
3927     /// </summary>
3928     void _RegisterTask(const typename details::_Task_ptr<_ResultType>::_Type & _TaskParam)
3929     {
3930         details::scoped_lock _LockHolder(_M_Impl->_M_taskListCritSec);
3931 #if _MSC_VER < 1800
3932         _TaskParam->_SetScheduledEvent();
3933 #endif
3934         //If an exception was already set on this event, then cancel the task with the stored exception.
3935         if (_M_Impl->_HasUserException())
3936         {
3937             _TaskParam->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
3938         }
3939         else if (_M_Impl->_M_fHasValue)
3940         {
3941 #if _MSC_VER >= 1800
3942             _TaskParam->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
3943 #else
3944             _TaskParam->_FinalizeAndRunContinuations(_M_Impl->_M_value);
3945 #endif
3946         }
3947         else
3948         {
3949             _M_Impl->_M_tasks.push_back(_TaskParam);
3950         }
3951     }
3952 
3953     std::shared_ptr<details::_Task_completion_event_impl<_ResultType>> _M_Impl;
3954 };
3955 
3956 /// <summary>
3957 ///     The <c>task_completion_event</c> class allows you to delay the execution of a task until a condition is satisfied,
3958 ///     or start a task in response to an external event.
3959 /// </summary>
3960 /// <remarks>
3961 ///     Use a task created from a task completion event when your scenario requires you to create a task that will complete, and
3962 ///     thereby have its continuations scheduled for execution, at some point in the future. The <c>task_completion_event</c> must
3963 ///     have the same type as the task you create, and calling the set method on the task completion event with a value of that type
3964 ///     will cause the associated task to complete, and provide that value as a result to its continuations.
3965 ///     <para>If the task completion event is never signaled, any tasks created from it will be canceled when it is destructed.</para>
3966 ///     <para><c>task_completion_event</c> behaves like a smart pointer, and should be passed by value.</para>
3967 /// </remarks>
3968 /// <seealso cref="task Class"/>
3969 /**/
3970 template<>
3971 class task_completion_event<void>
3972 {
3973 public:
3974     /// <summary>
3975     ///     Sets the task completion event.
3976     /// </summary>
3977     /// <returns>
3978     ///     The method returns <c>true</c> if it was successful in setting the event. It returns <c>false</c> if the event is already set.
3979     /// </returns>
3980     /// <remarks>
3981     ///     In the presence of multiple or concurrent calls to <c>set</c>, only the first call will succeed and its result (if any) will be stored in the
3982     ///     task completion event. The remaining sets are ignored and the method will return false. When you set a task completion event, all the
3983     ///     tasks created from that event will immediately complete, and its continuations, if any, will be scheduled. Task completion objects that have
3984     ///     a <typeparamref name="_ResultType"/> other than <c>void</c> will pass the value <paramref value="_Result"/> to their continuations.
3985     /// </remarks>
3986     /**/
3987     bool set() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3988     {
3989         return _M_unitEvent.set(details::_Unit_type());
3990     }
3991 #if _MSC_VER >= 1800
3992 
3993     template<typename _E>
3994     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
3995         bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3996     {
3997             return _M_unitEvent._Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
3998     }
3999 #endif
4000 
4001     /// <summary>
4002     ///     Propagates an exception to all tasks associated with this event.
4003     /// </summary>
4004     /// <param>
4005     ///     The exception_ptr that indicates the exception to set this event with.
4006     /// </param>
4007     /**/
4008     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4009         bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
4010     {
4011         // It is important that _ReturnAddress() evaluate to the instruction after the call instruction for set_exception.
4012 #if _MSC_VER >= 1800
4013             return _M_unitEvent._Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
4014 #else
4015             return _M_unitEvent._Cancel(_ExceptionPtr, _ReturnAddress());
4016 #endif
4017     }
4018 
4019     /// <summary>
4020     ///     Cancel the task_completion_event. Any task created using this event will be marked as canceled if it has
4021     ///     not already been set.
4022     /// </summary>
4023     void _Cancel() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
4024     {
4025         _M_unitEvent._Cancel();
4026     }
4027 
4028     /// <summary>
4029     ///     Cancel the task_completion_event with the exception holder provided. Any task created using this event will be canceled
4030     ///     with the same exception.
4031     /// </summary>
4032     void _Cancel(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
4033     {
4034         _M_unitEvent._Cancel(_ExHolder);
4035     }
4036 
4037     /// <summary>
4038     ///     Method that stores an exception in the task completion event. This is used internally by when_any.
4039     ///     Note, this does not cancel the task completion event. A task completion event with a stored exception
4040     ///     can bet set() successfully. If it is canceled, it will cancel with the stored exception, if one is present.
4041     /// </summary>
4042     bool _StoreException(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
4043     {
4044         return _M_unitEvent._StoreException(_ExHolder);
4045     }
4046 
4047     /// <summary>
4048     ///     Test whether current event has been either Set, or Canceled.
4049     /// </summary>
4050     bool _IsTriggered() const
4051     {
4052         return _M_unitEvent._IsTriggered();
4053     }
4054 
4055 private:
4056     template <typename T> friend class task; // task can register itself with the event by calling the private _RegisterTask
4057 
4058     /// <summary>
4059     ///     Register a task with this event. This function is called when a task is constructed using
4060     ///     a task_completion_event.
4061     /// </summary>
4062     void _RegisterTask(details::_Task_ptr<details::_Unit_type>::_Type _TaskParam)
4063     {
4064         _M_unitEvent._RegisterTask(_TaskParam);
4065     }
4066 
4067     // The void event contains an event a dummy type so common code can be used for events with void and non-void results.
4068     task_completion_event<details::_Unit_type> _M_unitEvent;
4069 };
4070 namespace details
4071 {
4072     //
4073     // Compile-time validation helpers
4074     //
4075 
4076     // Task constructor validation: issue helpful diagnostics for common user errors. Do not attempt full validation here.
4077     //
4078     // Anything callable is fine
4079     template<typename _ReturnType, typename _Ty>
4080     auto _IsValidTaskCtor(_Ty _Param, int, int, int, int, int, int, int) -> typename decltype(_Param(), std::true_type());
4081 
4082     // Anything callable with a task return value is fine
4083     template<typename _ReturnType, typename _Ty>
4084     auto _IsValidTaskCtor(_Ty _Param, int, int, int, int, int, int, ...) -> typename decltype(_Param(stdx::declval<task<_ReturnType>*>()), std::true_type());
4085 
4086     // Anything callable with a return value is fine
4087     template<typename _ReturnType, typename _Ty>
4088     auto _IsValidTaskCtor(_Ty _Param, int, int, int, int, int, ...) -> typename decltype(_Param(stdx::declval<_ReturnType*>()), std::true_type());
4089 
4090     // Anything that has GetResults is fine: this covers AsyncAction*
4091     template<typename _ReturnType, typename _Ty>
4092     auto _IsValidTaskCtor(_Ty _Param, int, int, int, int, ...) -> typename decltype(_Param->GetResults(), std::true_type());
4093 
4094     // Anything that has GetResults(TResult_abi*) is fine: this covers AsyncOperation*
4095     template<typename _ReturnType, typename _Ty>
4096     auto _IsValidTaskCtor(_Ty _Param, int, int, int, ...) -> typename decltype(_Param->GetResults(stdx::declval<decltype(_GetUnwrappedType(stdx::declval<_Ty>()))*>()), std::true_type());
4097 
4098     // Allow parameters with set: this covers task_completion_event
4099     template<typename _ReturnType, typename _Ty>
4100     auto _IsValidTaskCtor(_Ty _Param, int, int, ...) -> typename decltype(_Param.set(stdx::declval<_ReturnType>()), std::true_type());
4101 
4102     template<typename _ReturnType, typename _Ty>
4103     auto _IsValidTaskCtor(_Ty _Param, int, ...) -> typename decltype(_Param.set(), std::true_type());
4104 
4105     // All else is invalid
4106     template<typename _ReturnType, typename _Ty>
4107     std::false_type _IsValidTaskCtor(_Ty _Param, ...);
4108 
4109     template<typename _ReturnType, typename _Ty>
4110     void _ValidateTaskConstructorArgs(_Ty _Param)
4111     {
4112         (void)_Param;
4113         static_assert(std::is_same<decltype(details::_IsValidTaskCtor<_ReturnType>(_Param, 0, 0, 0, 0, 0, 0, 0)), std::true_type>::value,
4114             "incorrect argument for task constructor; can be a callable object, an asynchronous operation, or a task_completion_event"
4115             );
4116         static_assert(!(std::is_same<_Ty, _ReturnType>::value && details::_IsIAsyncInfo<_Ty>::_Value),
4117             "incorrect template argument for task; consider using the return type of the async operation");
4118     }
4119     // Helpers for create_async validation
4120     //
4121     // A parameter lambda taking no arguments is valid
4122     template<typename _ReturnType, typename _Ty>
4123     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int, int, int, int, int) -> typename decltype(_Param(), std::true_type());
4124 
4125     // A parameter lambda taking a result argument is valid
4126     template<typename _ReturnType, typename _Ty>
4127     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int, int, int, int, ...) -> typename decltype(_Param(stdx::declval<_ReturnType*>()), std::true_type());
4128 
4129     // A parameter lambda taking an cancellation_token argument is valid
4130     template<typename _ReturnType, typename _Ty>
4131     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int, int, int, ...) -> typename decltype(_Param(Concurrency::cancellation_token::none()), std::true_type());
4132 
4133     // A parameter lambda taking an cancellation_token argument and a result argument is valid
4134     template<typename _ReturnType, typename _Ty>
4135     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int, int, ...) -> typename decltype(_Param(Concurrency::cancellation_token::none(), stdx::declval<_ReturnType*>()), std::true_type());
4136 
4137     // A parameter lambda taking a progress report argument is valid
4138     template<typename _ReturnType, typename _Ty>
4139     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type());
4140 
4141     // A parameter lambda taking a progress report argument and a result argument is valid
4142     template<typename _ReturnType, typename _Ty>
4143     static auto _IsValidCreateAsync(_Ty _Param, int, int, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType(), stdx::declval<_ReturnType*>()), std::true_type());
4144 
4145     // A parameter lambda taking a progress report and a cancellation_token argument is valid
4146     template<typename _ReturnType, typename _Ty>
4147     static auto _IsValidCreateAsync(_Ty _Param, int, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType(), Concurrency::cancellation_token::none()), std::true_type());
4148 
4149     // A parameter lambda taking a progress report and a cancellation_token argument and a result argument is valid
4150     template<typename _ReturnType, typename _Ty>
4151     static auto _IsValidCreateAsync(_Ty _Param, int, ...) -> typename decltype(_Param(details::_ProgressReporterCtorArgType(), Concurrency::cancellation_token::none(), stdx::declval<_ReturnType*>()), std::true_type());
4152 
4153     // All else is invalid
4154     template<typename _ReturnType, typename _Ty>
4155     static std::false_type _IsValidCreateAsync(_Ty _Param, ...);
4156 }
4157 
4158 /// <summary>
4159 ///     The Parallel Patterns Library (PPL) <c>task</c> class. A <c>task</c> object represents work that can be executed asynchronously,
4160 ///     and concurrently with other tasks and parallel work produced by parallel algorithms in the Concurrency Runtime. It produces
4161 ///     a result of type <typeparamref name="_ResultType"/> on successful completion. Tasks of type <c>task&lt;void&gt;</c> produce no result.
4162 ///     A task can be waited upon and canceled independently of other tasks. It can also be composed with other tasks using
4163 ///     continuations(<c>then</c>), and join(<c>when_all</c>) and choice(<c>when_any</c>) patterns.
4164 /// </summary>
4165 /// <typeparam name="_ReturnType">
4166 ///     The result type of this task.
4167 /// </typeparam>
4168 /// <remarks>
4169 ///     For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.
4170 /// </remarks>
4171 /**/
4172 template<typename _ReturnType>
4173 class task
4174 {
4175 public:
4176     /// <summary>
4177     ///     The type of the result an object of this class produces.
4178     /// </summary>
4179     /**/
4180     typedef _ReturnType result_type;
4181 
4182     /// <summary>
4183     ///     Constructs a <c>task</c> object.
4184     /// </summary>
4185     /// <remarks>
4186     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
4187     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
4188     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
4189     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
4190     ///     completion event is set.</para>
4191     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
4192     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
4193     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4194     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
4195     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
4196     ///     and not when the lamda returns.</para>
4197     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
4198     ///     without the need for locks.</para>
4199     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
4200     ///     to Windows Store apps.</para>
4201     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4202     /// </remarks>
4203     /**/
4204     task() : _M_Impl(nullptr)
4205     {
4206         // The default constructor should create a task with a nullptr impl. This is a signal that the
4207         // task is not usable and should throw if any wait(), get() or then() APIs are used.
4208     }
4209 
4210     /// <summary>
4211     ///     Constructs a <c>task</c> object.
4212     /// </summary>
4213     /// <typeparam name="_Ty">
4214     ///     The type of the parameter from which the task is to be constructed.
4215     /// </typeparam>
4216     /// <param name="_Param">
4217     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a <c>task_completion_event&lt;result_type&gt;</c>
4218     ///     object, or a Windows::Foundation::IAsyncInfo if you are using tasks in your Windows Store app. The lambda or function
4219     ///     object should be a type equivalent to <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
4220     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
4221     /// </param>
4222     /// <param name="_Token">
4223     ///     The cancellation token to associate with this task. A task created without a cancellation token cannot be canceled. It implicitly receives
4224     ///     the token <c>cancellation_token::none()</c>.
4225     /// </param>
4226     /// <remarks>
4227     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
4228     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
4229     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
4230     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
4231     ///     completion event is set.</para>
4232     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
4233     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
4234     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4235     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
4236     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
4237     ///     and not when the lamda returns.</para>
4238     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
4239     ///     without the need for locks.</para>
4240     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
4241     ///     to Windows Store apps.</para>
4242     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4243     /// </remarks>
4244     /**/
4245     template<typename _Ty>
4246     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4247         explicit task(_Ty _Param)
4248     {
4249 #if _MSC_VER >= 1800
4250             task_options _TaskOptions;
4251 #endif
4252             details::_ValidateTaskConstructorArgs<_ReturnType, _Ty>(_Param);
4253 
4254 #if _MSC_VER >= 1800
4255             _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
4256 #else
4257             _CreateImpl(Concurrency::cancellation_token::none()._GetImplValue());
4258 #endif
4259             // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of the task constructor.
4260 #if _MSC_VER >= 1800
4261             _SetTaskCreationCallstack(_CAPTURE_CALLSTACK());
4262 #else
4263             _SetTaskCreationAddressHint(_ReturnAddress());
4264 #endif
4265             _TaskInitMaybeFunctor(_Param, details::_IsCallable<_ReturnType>(_Param, 0, 0, 0));
4266         }
4267 
4268     /// <summary>
4269     ///     Constructs a <c>task</c> object.
4270     /// </summary>
4271     /// <typeparam name="_Ty">
4272     ///     The type of the parameter from which the task is to be constructed.
4273     /// </typeparam>
4274     /// <param name="_Param">
4275     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a <c>task_completion_event&lt;result_type&gt;</c>
4276     ///     object, or a Windows::Foundation::IAsyncInfo if you are using tasks in your Windows Store app. The lambda or function
4277     ///     object should be a type equivalent to <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
4278     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
4279     /// </param>
4280     /// <param name="_Token">
4281     ///     The cancellation token to associate with this task. A task created without a cancellation token cannot be canceled. It implicitly receives
4282     ///     the token <c>cancellation_token::none()</c>.
4283     /// </param>
4284     /// <remarks>
4285     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
4286     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
4287     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
4288     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
4289     ///     completion event is set.</para>
4290     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
4291     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
4292     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4293     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
4294     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
4295     ///     and not when the lamda returns.</para>
4296     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
4297     ///     without the need for locks.</para>
4298     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
4299     ///     to Windows Store apps.</para>
4300     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4301     /// </remarks>
4302     /**/
4303     template<typename _Ty>
4304     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4305 #if _MSC_VER >= 1800
4306         explicit task(_Ty _Param, const task_options &_TaskOptions)
4307 #else
4308         explicit task(_Ty _Param, Concurrency::cancellation_token _Token)
4309 #endif
4310     {
4311             details::_ValidateTaskConstructorArgs<_ReturnType, _Ty>(_Param);
4312 
4313 #if _MSC_VER >= 1800
4314             _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
4315 #else
4316             _CreateImpl(_Token._GetImplValue());
4317 #endif
4318             // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of the task constructor.
4319 #if _MSC_VER >= 1800
4320             _SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
4321 #else
4322             _SetTaskCreationAddressHint(_ReturnAddress());
4323 #endif
4324             _TaskInitMaybeFunctor(_Param, details::_IsCallable<_ReturnType>(_Param, 0, 0, 0));
4325         }
4326 
4327     /// <summary>
4328     ///     Constructs a <c>task</c> object.
4329     /// </summary>
4330     /// <param name="_Other">
4331     ///     The source <c>task</c> object.
4332     /// </param>
4333     /// <remarks>
4334     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
4335     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
4336     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
4337     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
4338     ///     completion event is set.</para>
4339     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
4340     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
4341     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4342     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
4343     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
4344     ///     and not when the lamda returns.</para>
4345     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
4346     ///     without the need for locks.</para>
4347     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
4348     ///     to Windows Store apps.</para>
4349     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4350     /// </remarks>
4351     /**/
4352     task(const task& _Other) : _M_Impl(_Other._M_Impl) {}
4353 
4354     /// <summary>
4355     ///     Constructs a <c>task</c> object.
4356     /// </summary>
4357     /// <param name="_Other">
4358     ///     The source <c>task</c> object.
4359     /// </param>
4360     /// <remarks>
4361     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
4362     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
4363     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
4364     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
4365     ///     completion event is set.</para>
4366     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
4367     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
4368     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4369     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
4370     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
4371     ///     and not when the lamda returns.</para>
4372     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
4373     ///     without the need for locks.</para>
4374     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
4375     ///     to Windows Store apps.</para>
4376     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4377     /// </remarks>
4378     /**/
4379     task(task&& _Other) : _M_Impl(std::move(_Other._M_Impl)) {}
4380 
4381     /// <summary>
4382     ///     Replaces the contents of one <c>task</c> object with another.
4383     /// </summary>
4384     /// <param name="_Other">
4385     ///     The source <c>task</c> object.
4386     /// </param>
4387     /// <remarks>
4388     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents the same
4389     ///     actual task as <paramref name="_Other"/> does.
4390     /// </remarks>
4391     /**/
4392     task& operator=(const task& _Other)
4393     {
4394         if (this != &_Other)
4395         {
4396             _M_Impl = _Other._M_Impl;
4397         }
4398         return *this;
4399     }
4400 
4401     /// <summary>
4402     ///     Replaces the contents of one <c>task</c> object with another.
4403     /// </summary>
4404     /// <param name="_Other">
4405     ///     The source <c>task</c> object.
4406     /// </param>
4407     /// <remarks>
4408     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents the same
4409     ///     actual task as <paramref name="_Other"/> does.
4410     /// </remarks>
4411     /**/
4412     task& operator=(task&& _Other)
4413     {
4414         if (this != &_Other)
4415         {
4416             _M_Impl = std::move(_Other._M_Impl);
4417         }
4418         return *this;
4419     }
4420 
4421     /// <summary>
4422     ///     Adds a continuation task to this task.
4423     /// </summary>
4424     /// <typeparam name="_Function">
4425     ///     The type of the function object that will be invoked by this task.
4426     /// </typeparam>
4427     /// <param name="_Func">
4428     ///     The continuation function to execute when this task completes. This continuation function must take as input
4429     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
4430     ///     of the result this task produces.
4431     /// </param>
4432     /// <returns>
4433     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
4434     /// </returns>
4435     /// <remarks>
4436     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
4437     ///     to Windows Store apps.
4438     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4439     /// </remarks>
4440     /**/
4441     template<typename _Function>
4442     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4443         auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4444     {
4445 #if _MSC_VER >= 1800
4446             task_options _TaskOptions;
4447             details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
4448             return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
4449 #else
4450             auto _ContinuationTask = _ThenImpl<_ReturnType, _Function>(_Func, nullptr, task_continuation_context::use_default());
4451             // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
4452             _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
4453             return _ContinuationTask;
4454 #endif
4455         }
4456 
4457     /// <summary>
4458     ///     Adds a continuation task to this task.
4459     /// </summary>
4460     /// <typeparam name="_Function">
4461     ///     The type of the function object that will be invoked by this task.
4462     /// </typeparam>
4463     /// <param name="_Func">
4464     ///     The continuation function to execute when this task completes. This continuation function must take as input
4465     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
4466     ///     of the result this task produces.
4467     /// </param>
4468     /// <param name="_CancellationToken">
4469     ///     The cancellation token to associate with the continuation task. A continuation task that is created without a cancellation token will inherit
4470     ///     the token of its antecedent task.
4471     /// </param>
4472     /// <returns>
4473     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
4474     /// </returns>
4475     /// <remarks>
4476     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
4477     ///     to Windows Store apps.
4478     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4479     /// </remarks>
4480     /**/
4481     template<typename _Function>
4482     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4483 #if _MSC_VER >= 1800
4484         auto then(const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4485 #else
4486         auto then(const _Function& _Func, Concurrency::cancellation_token _CancellationToken) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4487 #endif
4488     {
4489 #if _MSC_VER >= 1800
4490             details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
4491             return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
4492 #else
4493         auto _ContinuationTask = _ThenImpl<_ReturnType, _Function>(_Func, _CancellationToken._GetImplValue(), task_continuation_context::use_default());
4494         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
4495         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
4496         return _ContinuationTask;
4497 #endif
4498     }
4499 #if _MSC_VER < 1800
4500     /// <summary>
4501     ///     Adds a continuation task to this task.
4502     /// </summary>
4503     /// <typeparam name="_Function">
4504     ///     The type of the function object that will be invoked by this task.
4505     /// </typeparam>
4506     /// <param name="_Func">
4507     ///     The continuation function to execute when this task completes. This continuation function must take as input
4508     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
4509     ///     of the result this task produces.
4510     /// </param>
4511     /// <param name="_ContinuationContext">
4512     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
4513     ///     Windows Store app. For more information, see <see cref="task_continuation_context Class">task_continuation_context</see>
4514     /// </param>
4515     /// <returns>
4516     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
4517     /// </returns>
4518     /// <remarks>
4519     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
4520     ///     to Windows Store apps.
4521     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4522     /// </remarks>
4523     /**/
4524     template<typename _Function>
4525     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4526         auto then(const _Function& _Func, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4527     {
4528         auto _ContinuationTask = _ThenImpl<_ReturnType, _Function>(_Func, nullptr, _ContinuationContext);
4529         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
4530         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
4531         return _ContinuationTask;
4532     }
4533 #endif
4534     /// <summary>
4535     ///     Adds a continuation task to this task.
4536     /// </summary>
4537     /// <typeparam name="_Function">
4538     ///     The type of the function object that will be invoked by this task.
4539     /// </typeparam>
4540     /// <param name="_Func">
4541     ///     The continuation function to execute when this task completes. This continuation function must take as input
4542     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
4543     ///     of the result this task produces.
4544     /// </param>
4545     /// <param name="_CancellationToken">
4546     ///     The cancellation token to associate with the continuation task. A continuation task that is created without a cancellation token will inherit
4547     ///     the token of its antecedent task.
4548     /// </param>
4549     /// <param name="_ContinuationContext">
4550     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
4551     ///     Windows Store app. For more information, see <see cref="task_continuation_context Class">task_continuation_context</see>
4552     /// </param>
4553     /// <returns>
4554     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
4555     /// </returns>
4556     /// <remarks>
4557     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
4558     ///     to Windows Store apps.
4559     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4560     /// </remarks>
4561     /**/
4562     template<typename _Function>
4563     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
4564         auto then(const _Function& _Func, Concurrency::cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4565     {
4566 #if _MSC_VER >= 1800
4567             task_options _TaskOptions(_CancellationToken, _ContinuationContext);
4568             details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
4569             return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
4570 #else
4571             auto _ContinuationTask = _ThenImpl<_ReturnType, _Function>(_Func, _CancellationToken._GetImplValue(), _ContinuationContext);
4572             // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
4573             _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
4574             return _ContinuationTask;
4575 #endif
4576         }
4577 
4578     /// <summary>
4579     ///     Waits for this task to reach a terminal state. It is possible for <c>wait</c> to execute the task inline, if all of the tasks
4580     ///     dependencies are satisfied, and it has not already been picked up for execution by a background worker.
4581     /// </summary>
4582     /// <returns>
4583     ///     A <c>task_status</c> value which could be either <c>completed</c> or <c>canceled</c>. If the task encountered an exception
4584     ///     during execution, or an exception was propagated to it from an antecedent task, <c>wait</c> will throw that exception.
4585     /// </returns>
4586     /**/
4587     task_status wait() const
4588     {
4589         if (_M_Impl == nullptr)
4590         {
4591             throw Concurrency::invalid_operation("wait() cannot be called on a default constructed task.");
4592         }
4593 
4594         return _M_Impl->_Wait();
4595     }
4596 
4597     /// <summary>
4598     ///     Returns the result this task produced. If the task is not in a terminal state, a call to <c>get</c> will wait for the task to
4599     ///     finish. This method does not return a value when called on a task with a <c>result_type</c> of <c>void</c>.
4600     /// </summary>
4601     /// <returns>
4602     ///     The result of the task.
4603     /// </returns>
4604     /// <remarks>
4605     ///     If the task is canceled, a call to <c>get</c> will throw a <see cref="task_canceled Class">task_canceled</see> exception. If the task
4606     ///     encountered an different exception or an exception was propagated to it from an antecedent task, a call to <c>get</c> will throw that exception.
4607     /// </remarks>
4608     /**/
4609     _ReturnType get() const
4610     {
4611         if (_M_Impl == nullptr)
4612         {
4613             throw Concurrency::invalid_operation("get() cannot be called on a default constructed task.");
4614         }
4615 
4616         if (_M_Impl->_Wait() == Concurrency::canceled)
4617         {
4618             throw Concurrency::task_canceled();
4619         }
4620 
4621         return _M_Impl->_GetResult();
4622     }
4623 #if _MSC_VER >= 1800
4624     /// <summary>
4625     ///     Determines if the task is completed.
4626     /// </summary>
4627     /// <returns>
4628     ///     True if the task has completed, false otherwise.
4629     /// </returns>
4630     /// <remarks>
4631     ///     The function returns true if the task is completed or canceled (with or without user exception).
4632     /// </remarks>
4633     bool is_done() const
4634     {
4635         if (!_M_Impl)
4636         {
4637             throw Concurrency::invalid_operation("is_done() cannot be called on a default constructed task.");
4638         }
4639 
4640         return _M_Impl->_IsDone();
4641     }
4642 
4643     /// <summary>
4644     ///     Returns the scheduler for this task
4645     /// </summary>
4646     /// <returns>
4647     ///     A pointer to the scheduler
4648     /// </returns>
4649     Concurrency::scheduler_ptr scheduler() const
4650     {
4651         if (!_M_Impl)
4652         {
4653             throw Concurrency::invalid_operation("scheduler() cannot be called on a default constructed task.");
4654         }
4655 
4656         return _M_Impl->_GetScheduler();
4657     }
4658 #endif
4659     /// <summary>
4660     ///     Determines whether the task unwraps a Windows Runtime <c>IAsyncInfo</c> interface or is descended from such a task.
4661     /// </summary>
4662     /// <returns>
4663     ///     <c>true</c> if the task unwraps an <c>IAsyncInfo</c> interface or is descended from such a task, <c>false</c> otherwise.
4664     /// </returns>
4665     /**/
4666     bool is_apartment_aware() const
4667     {
4668         if (_M_Impl == nullptr)
4669         {
4670             throw Concurrency::invalid_operation("is_apartment_aware() cannot be called on a default constructed task.");
4671         }
4672         return _M_Impl->_IsApartmentAware();
4673     }
4674 
4675     /// <summary>
4676     ///     Determines whether two <c>task</c> objects represent the same internal task.
4677     /// </summary>
4678     /// <returns>
4679     ///     <c>true</c> if the objects refer to the same underlying task, and <c>false</c> otherwise.
4680     /// </returns>
4681     /**/
4682     bool operator==(const task<_ReturnType>& _Rhs) const
4683     {
4684         return (_M_Impl == _Rhs._M_Impl);
4685     }
4686 
4687     /// <summary>
4688     ///     Determines whether two <c>task</c> objects represent different internal tasks.
4689     /// </summary>
4690     /// <returns>
4691     ///     <c>true</c> if the objects refer to different underlying tasks, and <c>false</c> otherwise.
4692     /// </returns>
4693     /**/
4694     bool operator!=(const task<_ReturnType>& _Rhs) const
4695     {
4696         return !operator==(_Rhs);
4697     }
4698 
4699     /// <summary>
4700     ///     Create an underlying task implementation.
4701     /// </summary>
4702 #if _MSC_VER >= 1800
4703     void _CreateImpl(Concurrency::details::_CancellationTokenState * _Ct, Concurrency::scheduler_ptr _Scheduler)
4704 #else
4705     void _CreateImpl(Concurrency::details::_CancellationTokenState * _Ct)
4706 #endif
4707     {
4708         _CONCRT_ASSERT(_Ct != nullptr);
4709 #if _MSC_VER >= 1800
4710         _M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct, _Scheduler);
4711 #else
4712         _M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct);
4713 #endif
4714         if (_Ct != Concurrency::details::_CancellationTokenState::_None())
4715         {
4716 #if _MSC_VER >= 1800
4717             _M_Impl->_RegisterCancellation(_M_Impl);
4718 #else
4719             _M_Impl->_RegisterCancellation();
4720 #endif
4721         }
4722     }
4723 
4724     /// <summary>
4725     ///     Return the underlying implementation for this task.
4726     /// </summary>
4727     const typename details::_Task_ptr<_ReturnType>::_Type & _GetImpl() const
4728     {
4729         return _M_Impl;
4730     }
4731 
4732     /// <summary>
4733     ///     Set the implementation of the task to be the supplied implementaion.
4734     /// </summary>
4735     void _SetImpl(const typename details::_Task_ptr<_ReturnType>::_Type & _Impl)
4736     {
4737         _CONCRT_ASSERT(_M_Impl == nullptr);
4738         _M_Impl = _Impl;
4739     }
4740 
4741     /// <summary>
4742     ///     Set the implementation of the task to be the supplied implementaion using a move instead of a copy.
4743     /// </summary>
4744     void _SetImpl(typename details::_Task_ptr<_ReturnType>::_Type && _Impl)
4745     {
4746         _CONCRT_ASSERT(_M_Impl == nullptr);
4747         _M_Impl = std::move(_Impl);
4748     }
4749 
4750     /// <summary>
4751     ///     Sets a property determining whether the task is apartment aware.
4752     /// </summary>
4753     void _SetAsync(bool _Async = true)
4754     {
4755         _GetImpl()->_SetAsync(_Async);
4756     }
4757 
4758     /// <summary>
4759     ///     Sets a field in the task impl to the return address for calls to the task constructors and the then method.
4760     /// </summary>
4761 #if _MSC_VER >= 1800
4762     void _SetTaskCreationCallstack(const details::_TaskCreationCallstack &_callstack)
4763     {
4764         _GetImpl()->_SetTaskCreationCallstack(_callstack);
4765     }
4766 #else
4767     void _SetTaskCreationAddressHint(void* _Address)
4768     {
4769         _GetImpl()->_SetTaskCreationAddressHint(_Address);
4770     }
4771 #endif
4772     /// <summary>
4773     ///     An internal version of then that takes additional flags and always execute the continuation inline by default.
4774     ///     When _ForceInline is set to false, continuations inlining will be limited to default _DefaultAutoInline.
4775     ///     This function is Used for runtime internal continuations only.
4776     /// </summary>
4777     template<typename _Function>
4778 #if _MSC_VER >= 1800
4779     auto _Then(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState,
4780         details::_TaskInliningMode _InliningMode = Concurrency::details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4781     {
4782         // inherit from antecedent
4783         auto _Scheduler = _GetImpl()->_GetScheduler();
4784 
4785         return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
4786     }
4787 #else
4788     auto _Then(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState, bool _Aggregating,
4789         details::_TaskInliningMode _InliningMode = Concurrency::details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
4790     {
4791         return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Aggregating, _InliningMode);
4792     }
4793 #endif
4794 
4795 private:
4796     template <typename T> friend class task;
4797 
4798     // A helper class template that transforms an intial task lambda returns void into a lambda that returns a non-void type (details::_Unit_type is used
4799     // to substitute for void). This is to minimize the special handling required for 'void'.
4800     template<typename _RetType>
4801     class _Init_func_transformer
4802     {
4803     public:
4804         static auto _Perform(std::function<HRESULT(_RetType*)> _Func) -> decltype(_Func)
4805         {
4806             return _Func;
4807         }
4808     };
4809 
4810     template<>
4811     class _Init_func_transformer<void>
4812     {
4813     public:
4814         static auto _Perform(std::function<HRESULT(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
4815         {
4816             return details::_MakeVoidToUnitFunc(_Func);
4817         }
4818     };
4819 
4820     // The task handle type used to construct an 'initial task' - a task with no dependents.
4821     template <typename _InternalReturnType, typename _Function, typename _TypeSelection>
4822     struct _InitialTaskHandle :
4823         details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore>
4824     {
4825         _Function _M_function;
4826         _InitialTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _TaskImpl, const _Function & _Function) : _M_function(_Function), _PPLTaskHandle(_TaskImpl)
4827         {
4828         }
4829         virtual ~_InitialTaskHandle() {}
4830 
4831 #if _MSC_VER >= 1800
4832         template <typename _Func, typename _RetArg>
4833         auto _LogWorkItemAndInvokeUserLambda(_Func && _func, _RetArg && _retArg) const -> decltype(_func(std::forward<_RetArg>(_retArg)))
4834         {
4835             details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
4836             return _func(std::forward<_RetArg>(_retArg));
4837         }
4838 #endif
4839 
4840         void _Perform() const
4841         {
4842             _Init(_TypeSelection());
4843         }
4844 #if _MSC_VER >= 1800
4845 
4846         void _SyncCancelAndPropagateException() const
4847         {
4848             this->_M_pTask->_Cancel(true);
4849         }
4850 #endif
4851         //
4852         // Overload 0: returns _InternalReturnType
4853         //
4854         // This is the most basic task with no unwrapping
4855         //
4856         void _Init(details::_TypeSelectorNoAsync) const
4857         {
4858             _ReturnType retVal;
4859 #if _MSC_VER >= 1800
4860             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Init_func_transformer<_InternalReturnType>::_Perform(_M_function), &retVal);
4861 #else
4862             HRESULT hr = _Init_func_transformer<_InternalReturnType>::_Perform(_M_function)(&retVal);
4863 #endif
4864             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4865             _M_pTask->_FinalizeAndRunContinuations(retVal);
4866         }
4867 
4868         //
4869         // Overload 1: returns IAsyncOperation<_InternalReturnType>*
4870         //                   or
4871         //             returns task<_InternalReturnType>
4872         //
4873         // This is task whose functor returns an async operation or a task which will be unwrapped for continuation
4874         // Depending on the output type, the right _AsyncInit gets invoked
4875         //
4876         void _Init(details::_TypeSelectorAsyncTask) const
4877         {
4878             task<_InternalReturnType> retVal;
4879 #if _MSC_VER >= 1800
4880             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, &retVal);
4881 #else
4882             HRESULT hr = _M_function(&retVal);
4883 #endif
4884             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4885             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(_M_pTask, retVal);
4886         }
4887         void _Init(details::_TypeSelectorAsyncOperation) const
4888         {
4889             _ReturnType retVal;
4890 #if _MSC_VER >= 1800
4891             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, &retVal);
4892 #else
4893             HRESULT hr = _M_function(&retVal);
4894 #endif
4895             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4896             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(_M_pTask,
4897                 Microsoft::WRL::Make<details::_IAsyncOperationToAsyncOperationConverter<_InternalReturnType>>(retVal).Get());
4898         }
4899 
4900         //
4901         // Overload 2: returns IAsyncAction*
4902         //
4903         // This is task whose functor returns an async action which will be unwrapped for continuation
4904         //
4905         void _Init(details::_TypeSelectorAsyncAction) const
4906         {
4907             _ReturnType retVal;
4908 #if _MSC_VER >= 1800
4909             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, &retVal);
4910 #else
4911             HRESULT hr = _M_function(&retVal);
4912 #endif
4913             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4914             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(_M_pTask, Microsoft::WRL::Make<details::_IAsyncActionToAsyncOperationConverter>(retVal).Get());
4915         }
4916 
4917         //
4918         // Overload 3: returns IAsyncOperationWithProgress<_InternalReturnType, _ProgressType>*
4919         //
4920         // This is task whose functor returns an async operation with progress which will be unwrapped for continuation
4921         //
4922         void _Init(details::_TypeSelectorAsyncOperationWithProgress) const
4923         {
4924             typedef details::_GetProgressType<decltype(_M_function())>::_Value _ProgressType;
4925             _ReturnType retVal;
4926 #if _MSC_VER >= 1800
4927             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, &retVal);
4928 #else
4929             HRESULT hr = _M_function(&retVal);
4930 #endif
4931             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4932             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(_M_pTask,
4933                 Microsoft::WRL::Make<details::_IAsyncOperationWithProgressToAsyncOperationConverter<_InternalReturnType, _ProgressType>>(retVal).Get());
4934         }
4935 
4936         //
4937         // Overload 4: returns IAsyncActionWithProgress<_ProgressType>*
4938         //
4939         // This is task whose functor returns an async action with progress which will be unwrapped for continuation
4940         //
4941         void _Init(details::_TypeSelectorAsyncActionWithProgress) const
4942         {
4943             typedef details::_GetProgressType<decltype(_M_function())>::_Value _ProgressType;
4944             _ReturnType retVal;
4945 #if _MSC_VER >= 1800
4946             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, &retVal);
4947 #else
4948             HRESULT hr = _M_function(&retVal);
4949 #endif
4950             if (FAILED(hr)) throw std::make_exception_ptr(hr);
4951             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(_M_pTask,
4952                 Microsoft::WRL::Make<details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>>(retVal).Get());
4953         }
4954     };
4955 
4956     /// <summary>
4957     ///     A helper class template that transforms a continuation lambda that either takes or returns void, or both, into a lambda that takes and returns a
4958     ///     non-void type (details::_Unit_type is used to substitute for void). This is to minimize the special handling required for 'void'.
4959     /// </summary>
4960     template<typename _InpType, typename _OutType>
4961     class _Continuation_func_transformer
4962     {
4963     public:
4964         static auto _Perform(std::function<HRESULT(_InpType, _OutType*)> _Func) -> decltype(_Func)
4965         {
4966             return _Func;
4967         }
4968     };
4969 
4970     template<typename _OutType>
4971     class _Continuation_func_transformer<void, _OutType>
4972     {
4973     public:
4974         static auto _Perform(std::function<HRESULT(_OutType*)> _Func) -> decltype(details::_MakeUnitToTFunc<_OutType>(_Func))
4975         {
4976             return details::_MakeUnitToTFunc<_OutType>(_Func);
4977         }
4978     };
4979 
4980     template<typename _InType>
4981     class _Continuation_func_transformer<_InType, void>
4982     {
4983     public:
4984         static auto _Perform(std::function<HRESULT(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc<_InType>(_Func))
4985         {
4986             return details::_MakeTToUnitFunc<_InType>(_Func);
4987         }
4988     };
4989 
4990     template<>
4991     class _Continuation_func_transformer<void, void>
4992     {
4993     public:
4994         static auto _Perform(std::function<HRESULT(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
4995         {
4996             return details::_MakeUnitToUnitFunc(_Func);
4997         }
4998     };
4999     /// <summary>
5000     ///     The task handle type used to create a 'continuation task'.
5001     /// </summary>
5002     template <typename _InternalReturnType, typename _ContinuationReturnType, typename _Function, typename _IsTaskBased, typename _TypeSelection>
5003     struct _ContinuationTaskHandle :
5004         details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
5005         _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
5006     {
5007         typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type _NormalizedContinuationReturnType;
5008 
5009         typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl;
5010         _Function _M_function;
5011 
5012         _ContinuationTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _AncestorImpl,
5013             const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl,
5014             const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode _InliningMode) :
5015 #if _MSC_VER >= 1800
5016             details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
5017             _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
5018             ::_PPLTaskHandle(_ContinuationImpl)
5019             , _M_ancestorTaskImpl(_AncestorImpl)
5020             , _M_function(_Func)
5021 #else
5022             _M_ancestorTaskImpl(_AncestorImpl), _PPLTaskHandle(_ContinuationImpl), _M_function(_Func)
5023 #endif
5024         {
5025             _M_isTaskBasedContinuation = _IsTaskBased::value;
5026             _M_continuationContext = _Context;
5027             _M_continuationContext._Resolve(_AncestorImpl->_IsApartmentAware());
5028             _M_inliningMode = _InliningMode;
5029         }
5030 
5031         virtual ~_ContinuationTaskHandle() {}
5032 
5033 #if _MSC_VER >= 1800
5034         template <typename _Func, typename _Arg, typename _RetArg>
5035         auto _LogWorkItemAndInvokeUserLambda(_Func && _func, _Arg && _value, _RetArg && _retArg) const -> decltype(_func(std::forward<_Arg>(_value), std::forward<_RetArg>(_retArg)))
5036         {
5037             details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
5038             return _func(std::forward<_Arg>(_value), std::forward<_RetArg>(_retArg));
5039         }
5040 #endif
5041 
5042         void _Perform() const
5043         {
5044             _Continue(_IsTaskBased(), _TypeSelection());
5045         }
5046 
5047 #if _MSC_VER >= 1800
5048         void _SyncCancelAndPropagateException() const
5049         {
5050             if (_M_ancestorTaskImpl->_HasUserException())
5051             {
5052                 // If the ancestor encountered an exception, transfer the exception to the continuation
5053                 // This traverses down the tree to propagate the exception.
5054                 this->_M_pTask->_CancelWithExceptionHolder(_M_ancestorTaskImpl->_GetExceptionHolder(), true);
5055             }
5056             else
5057             {
5058                 // If the ancestor was canceled, then your own execution should be canceled.
5059                 // This traverses down the tree to cancel it.
5060                 this->_M_pTask->_Cancel(true);
5061             }
5062         }
5063 #endif
5064 
5065         //
5066         // Overload 0-0: _InternalReturnType -> _TaskType
5067         //
5068         // This is a straight task continuation which simply invokes its target with the ancestor's completion argument
5069         //
5070         void _Continue(std::false_type, details::_TypeSelectorNoAsync) const
5071         {
5072             _NormalizedContinuationReturnType retVal;
5073 #if _MSC_VER >= 1800
5074             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _ContinuationReturnType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &retVal);
5075 #else
5076             HRESULT hr =_Continuation_func_transformer<_InternalReturnType, _ContinuationReturnType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &retVal);
5077 #endif
5078             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5079             _M_pTask->_FinalizeAndRunContinuations(retVal);
5080         }
5081 
5082         //
5083         // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>*
5084         //               or
5085         //               _InternalReturnType -> task<_TaskType>
5086         //
5087         // This is a straight task continuation which returns an async operation or a task which will be unwrapped for continuation
5088         // Depending on the output type, the right _AsyncInit gets invoked
5089         //
5090         void _Continue(std::false_type, details::_TypeSelectorAsyncTask) const
5091         {
5092             typedef typename details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
5093             _FuncOutputType retVal;
5094 #if _MSC_VER >= 1800
5095             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &retVal);
5096 #else
5097             HRESULT hr = _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &retVal);
5098 #endif
5099             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5100             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
5101                 _M_pTask,
5102                 retVal
5103                 );
5104         }
5105         void _Continue(std::false_type, details::_TypeSelectorAsyncOperation) const
5106         {
5107             typedef typename details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
5108             _FuncOutputType retVal;
5109 #if _MSC_VER >= 1800
5110             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &retVal);
5111 #else
5112             HRESULT hr = _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &retVal);
5113 #endif
5114             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5115             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
5116                 _M_pTask,
5117                 Microsoft::WRL::Make<details::_IAsyncOperationToAsyncOperationConverter<_ContinuationReturnType>>(retVal).Get());
5118         }
5119 
5120         //
5121         // Overload 0-2: _InternalReturnType -> IAsyncAction*
5122         //
5123         // This is a straight task continuation which returns an async action which will be unwrapped for continuation
5124         //
5125         void _Continue(std::false_type, details::_TypeSelectorAsyncAction) const
5126         {
5127             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
5128             _FuncOutputType retVal;
5129 #if _MSC_VER >= 1800
5130             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &retVal);
5131 #else
5132             HRESULT hr = _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &retVal);
5133 #endif
5134             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5135             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
5136                 _M_pTask,
5137                 Microsoft::WRL::Make<details::_IAsyncActionToAsyncOperationConverter>(
5138                 retVal).Get());
5139         }
5140 
5141         //
5142         // Overload 0-3: _InternalReturnType -> IAsyncOperationWithProgress<_TaskType, _ProgressType>*
5143         //
5144         // This is a straight task continuation which returns an async operation with progress which will be unwrapped for continuation
5145         //
5146         void _Continue(std::false_type, details::_TypeSelectorAsyncOperationWithProgress) const
5147         {
5148             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
5149 
5150             _FuncOutputType _OpWithProgress;
5151 #if _MSC_VER >= 1800
5152             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &_OpWithProgress);
5153 #else
5154             HRESULT hr = _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &_OpWithProgress);
5155 #endif
5156             typedef details::_GetProgressType<decltype(_OpWithProgress)>::_Value _ProgressType;
5157 
5158             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5159             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
5160                 _M_pTask,
5161                 Microsoft::WRL::Make<details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>>(_OpWithProgress).Get());
5162         }
5163 
5164         //
5165         // Overload 0-4: _InternalReturnType -> IAsyncActionWithProgress<_ProgressType>*
5166         //
5167         // This is a straight task continuation which returns an async action with progress which will be unwrapped for continuation
5168         //
5169         void _Continue(std::false_type, details::_TypeSelectorAsyncActionWithProgress) const
5170         {
5171             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
5172 
5173             _FuncOutputType _OpWithProgress;
5174 #if _MSC_VER >= 1800
5175             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult(), &_OpWithProgress);
5176 #else
5177             HRESULT hr = _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function)(_M_ancestorTaskImpl->_GetResult(), &_OpWithProgress);
5178 #endif
5179             typedef details::_GetProgressType<decltype(_OpWithProgress)>::_Value _ProgressType;
5180 
5181             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5182             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
5183                 _M_pTask,
5184                 Microsoft::WRL::Make<details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>>(_OpWithProgress).Get());
5185         }
5186 
5187 
5188         //
5189         // Overload 1-0: task<_InternalReturnType> -> _TaskType
5190         //
5191         // This is an exception handling type of continuation which takes the task rather than the task's result.
5192         //
5193         void _Continue(std::true_type, details::_TypeSelectorNoAsync) const
5194         {
5195             typedef task<_InternalReturnType> _FuncInputType;
5196             task<_InternalReturnType> _ResultTask;
5197             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5198             _NormalizedContinuationReturnType retVal;
5199 #if _MSC_VER >= 1800
5200             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_FuncInputType, _ContinuationReturnType>::_Perform(_M_function), std::move(_ResultTask), &retVal);
5201 #else
5202             HRESULT hr = _Continuation_func_transformer<_FuncInputType, _ContinuationReturnType>::_Perform(_M_function)(std::move(_ResultTask), &retVal);
5203 #endif
5204             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5205             _M_pTask->_FinalizeAndRunContinuations(retVal);
5206         }
5207 
5208         //
5209         // Overload 1-1: task<_InternalReturnType> -> IAsyncOperation<_TaskType>^
5210         //                                            or
5211         //                                            task<_TaskType>
5212         //
5213         // This is an exception handling type of continuation which takes the task rather than
5214         // the task's result. It also returns an async operation or a task which will be unwrapped
5215         // for continuation
5216         //
5217         void _Continue(std::true_type, details::_TypeSelectorAsyncTask) const
5218         {
5219             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
5220             task<_InternalReturnType> _ResultTask;
5221             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5222             _ContinuationReturnType retVal;
5223 #if _MSC_VER >= 1800
5224             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask), &retVal);
5225 #else
5226             HRESULT hr = _M_function(std::move(_ResultTask), &retVal);
5227 #endif
5228             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5229             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(_M_pTask, retVal);
5230         }
5231         void _Continue(std::true_type, details::_TypeSelectorAsyncOperation) const
5232         {
5233             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
5234             task<_InternalReturnType> _ResultTask;
5235             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5236             _ContinuationReturnType retVal;
5237 #if _MSC_VER >= 1800
5238             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask), &retVal);
5239 #else
5240             HRESULT hr = _M_function(std::move(_ResultTask), &retVal);
5241 #endif
5242             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5243             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(_M_pTask,
5244                 Microsoft::WRL::Make<details::_IAsyncOperationToAsyncOperationConverter<_ContinuationReturnType>>(retVal));
5245         }
5246 
5247         //
5248         // Overload 1-2: task<_InternalReturnType> -> IAsyncAction*
5249         //
5250         // This is an exception handling type of continuation which takes the task rather than
5251         // the task's result. It also returns an async action which will be unwrapped for continuation
5252         //
5253         void _Continue(std::true_type, details::_TypeSelectorAsyncAction) const
5254         {
5255             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
5256             task<_InternalReturnType> _ResultTask;
5257             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5258             _ContinuationReturnType retVal;
5259 #if _MSC_VER >= 1800
5260             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask), &retVal);
5261 #else
5262             HRESULT hr = _M_function(std::move(_ResultTask), &retVal);
5263 #endif
5264             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5265             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(_M_pTask,
5266                 Microsoft::WRL::Make<details::_IAsyncActionToAsyncOperationConverter>(retVal));
5267         }
5268 
5269         //
5270         // Overload 1-3: task<_InternalReturnType> -> IAsyncOperationWithProgress<_TaskType, _ProgressType>*
5271         //
5272         // This is an exception handling type of continuation which takes the task rather than
5273         // the task's result. It also returns an async operation with progress which will be unwrapped
5274         // for continuation
5275         //
5276         void _Continue(std::true_type, details::_TypeSelectorAsyncOperationWithProgress) const
5277         {
5278             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
5279             task<_InternalReturnType> _ResultTask;
5280             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5281 
5282             typedef details::_GetProgressType<decltype(_M_function(_ResultTask))>::_Value _ProgressType;
5283             _ContinuationReturnType retVal;
5284 #if _MSC_VER >= 1800
5285             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask), &retVal);
5286 #else
5287             HRESULT hr = _M_function(std::move(_ResultTask), &retVal);
5288 #endif
5289             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5290             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(_M_pTask,
5291                 Microsoft::WRL::Make<details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>>(retVal));
5292         }
5293 
5294         //
5295         // Overload 1-4: task<_InternalReturnType> -> IAsyncActionWithProgress<_ProgressType>*
5296         //
5297         // This is an exception handling type of continuation which takes the task rather than
5298         // the task's result. It also returns an async operation with progress which will be unwrapped
5299         // for continuation
5300         //
5301         void _Continue(std::true_type, details::_TypeSelectorAsyncActionWithProgress) const
5302         {
5303             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
5304             task<_InternalReturnType> _ResultTask;
5305             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
5306 
5307             typedef details::_GetProgressType<decltype(_M_function(_ResultTask))>::_Value _ProgressType;
5308             _ContinuationReturnType retVal;
5309 #if _MSC_VER >= 1800
5310             HRESULT hr = _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask), &retVal);
5311 #else
5312             HRESULT hr = _M_function(std::move(_ResultTask), &retVal);
5313 #endif
5314             if (FAILED(hr)) throw std::make_exception_ptr(hr);
5315             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(_M_pTask,
5316                 Microsoft::WRL::Make<details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>>(retVal));
5317         }
5318     };
5319     /// <summary>
5320     ///     Initializes a task using a lambda, function pointer or function object.
5321     /// </summary>
5322     template<typename _InternalReturnType, typename _Function>
5323     void _TaskInitWithFunctor(const _Function& _Func)
5324     {
5325         typedef details::_InitFunctorTypeTraits<_InternalReturnType, details::_FunctionTypeTraits<_Function, void>::_FuncRetType> _Async_type_traits;
5326 
5327         _M_Impl->_M_fFromAsync = _Async_type_traits::_IsAsyncTask;
5328         _M_Impl->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
5329 #if _MSC_VER >= 1800
5330         _M_Impl->_M_taskEventLogger._LogScheduleTask(false);
5331 #endif
5332         _M_Impl->_ScheduleTask(new _InitialTaskHandle<_InternalReturnType, _Function, typename _Async_type_traits::_AsyncKind>(_GetImpl(), _Func), Concurrency::details::_NoInline);
5333     }
5334 
5335     /// <summary>
5336     ///     Initializes a task using a task completion event.
5337     /// </summary>
5338     void _TaskInitNoFunctor(task_completion_event<_ReturnType>& _Event)
5339     {
5340         _Event._RegisterTask(_M_Impl);
5341     }
5342 
5343     /// <summary>
5344     ///     Initializes a task using an asynchronous operation IAsyncOperation<T>*
5345     /// </summary>
5346     template<typename _Result, typename _OpType, typename _CompHandlerType, typename _ResultType>
5347     void _TaskInitAsyncOp(details::_AsyncInfoImpl<_OpType, _CompHandlerType, _ResultType>* _AsyncOp)
5348     {
5349         _M_Impl->_M_fFromAsync = true;
5350 #if _MSC_VER < 1800
5351         _M_Impl->_SetScheduledEvent();
5352 #endif
5353         // Mark this task as started here since we can set the state in the constructor without acquiring a lock. Once _AsyncInit
5354         // returns a completion could execute concurrently and the task must be fully initialized before that happens.
5355         _M_Impl->_M_TaskState = details::_Task_impl_base::_Started;
5356         // Pass the shared pointer into _AsyncInit for storage in the Async Callback.
5357         details::_Task_impl_base::_AsyncInit<_ReturnType, _Result>(_M_Impl, _AsyncOp);
5358     }
5359 
5360     /// <summary>
5361     ///     Initializes a task using an asynchronous operation IAsyncOperation<T>*
5362     /// </summary>
5363     template<typename _Result>
5364     void _TaskInitNoFunctor(ABI::Windows::Foundation::IAsyncOperation<_Result>* _AsyncOp)
5365     {
5366         _TaskInitAsyncOp<_Result>(Microsoft::WRL::Make<details::_IAsyncOperationToAsyncOperationConverter<_Result>>(_AsyncOp).Get());
5367     }
5368 
5369     /// <summary>
5370     ///     Initializes a task using an asynchronous operation with progress IAsyncOperationWithProgress<T, P>*
5371     /// </summary>
5372     template<typename _Result, typename _Progress>
5373     void _TaskInitNoFunctor(ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>* _AsyncOp)
5374     {
5375         _TaskInitAsyncOp<_Result>(Microsoft::WRL::Make<details::_IAsyncOperationWithProgressToAsyncOperationConverter<_Result, _Progress>>(_AsyncOp).Get());
5376     }
5377     /// <summary>
5378     ///     Initializes a task using a callable object.
5379     /// </summary>
5380     template<typename _Function>
5381     void _TaskInitMaybeFunctor(_Function & _Func, std::true_type)
5382     {
5383         _TaskInitWithFunctor<_ReturnType, _Function>(_Func);
5384     }
5385 
5386     /// <summary>
5387     ///     Initializes a task using a non-callable object.
5388     /// </summary>
5389     template<typename _Ty>
5390     void _TaskInitMaybeFunctor(_Ty & _Param, std::false_type)
5391     {
5392         _TaskInitNoFunctor(_Param);
5393     }
5394 #if _MSC_VER >= 1800
5395     template<typename _InternalReturnType, typename _Function>
5396     auto _ThenImpl(const _Function& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
5397     {
5398         if (!_M_Impl)
5399         {
5400             throw Concurrency::invalid_operation("then() cannot be called on a default constructed task.");
5401         }
5402 
5403         Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
5404         auto _Scheduler = _TaskOptions.has_scheduler() ? _TaskOptions.get_scheduler() : _GetImpl()->_GetScheduler();
5405         auto _CreationStack = details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : details::_TaskCreationCallstack();
5406         return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack);
5407     }
5408 #endif
5409     /// <summary>
5410     ///     The one and only implementation of then for void and non-void tasks.
5411     /// </summary>
5412     template<typename _InternalReturnType, typename _Function>
5413 #if _MSC_VER >= 1800
5414     auto _ThenImpl(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, Concurrency::scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
5415         details::_TaskInliningMode _InliningMode = Concurrency::details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
5416 #else
5417     auto _ThenImpl(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext,
5418         bool _Aggregating = false, details::_TaskInliningMode _InliningMode = Concurrency::details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
5419 #endif
5420     {
5421         if (_M_Impl == nullptr)
5422         {
5423             throw Concurrency::invalid_operation("then() cannot be called on a default constructed task.");
5424         }
5425 
5426         typedef details::_FunctionTypeTraits<_Function, _InternalReturnType> _Function_type_traits;
5427         typedef details::_TaskTypeTraits<typename _Function_type_traits::_FuncRetType> _Async_type_traits;
5428         typedef typename _Async_type_traits::_TaskRetType _TaskType;
5429 
5430         //
5431         // A **nullptr** token state indicates that it was not provided by the user. In this case, we inherit the antecedent's token UNLESS this is a
5432         // an exception handling continuation. In that case, we break the chain with a _None. That continuation is never canceled unless the user
5433         // explicitly passes the same token.
5434         //
5435         if (_PTokenState == nullptr)
5436         {
5437 #if _MSC_VER >= 1800
5438             if (_Function_type_traits::_Takes_task::value)
5439 #else
5440             if (_Function_type_traits::_Takes_task())
5441 #endif
5442             {
5443                 _PTokenState = Concurrency::details::_CancellationTokenState::_None();
5444             }
5445             else
5446             {
5447                 _PTokenState = _GetImpl()->_M_pTokenState;
5448             }
5449         }
5450 
5451         task<_TaskType> _ContinuationTask;
5452 #if _MSC_VER >= 1800
5453         _ContinuationTask._CreateImpl(_PTokenState, _Scheduler);
5454 #else
5455         _ContinuationTask._CreateImpl(_PTokenState);
5456 #endif
5457         _ContinuationTask._GetImpl()->_M_fFromAsync = (_GetImpl()->_M_fFromAsync || _Async_type_traits::_IsAsyncTask);
5458 #if _MSC_VER < 1800
5459         _ContinuationTask._GetImpl()->_M_fRuntimeAggregate = _Aggregating;
5460 #endif
5461         _ContinuationTask._GetImpl()->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
5462 #if _MSC_VER >= 1800
5463         _ContinuationTask._SetTaskCreationCallstack(_CreationStack);
5464 #endif
5465         _GetImpl()->_ScheduleContinuation(new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>(
5466             _GetImpl(), _ContinuationTask._GetImpl(), _Func, _ContinuationContext, _InliningMode));
5467 
5468         return _ContinuationTask;
5469     }
5470 
5471     // The underlying implementation for this task
5472     typename details::_Task_ptr<_ReturnType>::_Type _M_Impl;
5473 };
5474 
5475 /// <summary>
5476 ///     The Parallel Patterns Library (PPL) <c>task</c> class. A <c>task</c> object represents work that can be executed asynchronously,
5477 ///     and concurrently with other tasks and parallel work produced by parallel algorithms in the Concurrency Runtime. It produces
5478 ///     a result of type <typeparamref name="_ResultType"/> on successful completion. Tasks of type <c>task&lt;void&gt;</c> produce no result.
5479 ///     A task can be waited upon and canceled independently of other tasks. It can also be composed with other tasks using
5480 ///     continuations(<c>then</c>), and join(<c>when_all</c>) and choice(<c>when_any</c>) patterns.
5481 /// </summary>
5482 /// <remarks>
5483 ///     For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.
5484 /// </remarks>
5485 /**/
5486 template<>
5487 class task<void>
5488 {
5489 public:
5490     /// <summary>
5491     ///     The type of the result an object of this class produces.
5492     /// </summary>
5493     /**/
5494     typedef void result_type;
5495 
5496     /// <summary>
5497     ///     Constructs a <c>task</c> object.
5498     /// </summary>
5499     /// <remarks>
5500     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
5501     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
5502     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
5503     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
5504     ///     completion event is set.</para>
5505     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
5506     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
5507     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
5508     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
5509     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
5510     ///     and not when the lamda returns.</para>
5511     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
5512     ///     without the need for locks.</para>
5513     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
5514     ///     to Windows Store apps.</para>
5515     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5516     /// </remarks>
5517     /**/
5518     task() : _M_unitTask()
5519     {
5520         // The default constructor should create a task with a nullptr impl. This is a signal that the
5521         // task is not usable and should throw if any wait(), get() or then() APIs are used.
5522     }
5523 #if _MSC_VER < 1800
5524     /// <summary>
5525     ///     Constructs a <c>task</c> object.
5526     /// </summary>
5527     /// <typeparam name="_Ty">
5528     ///     The type of the parameter from which the task is to be constructed.
5529     /// </typeparam>
5530     /// <param name="_Param">
5531     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a <c>task_completion_event&lt;result_type&gt;</c>
5532     ///     object, or a Windows::Foundation::IAsyncInfo if you are using tasks in your Windows Store app. The lambda or function
5533     ///     object should be a type equivalent to <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
5534     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
5535     /// </param>
5536     /// <remarks>
5537     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
5538     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
5539     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
5540     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
5541     ///     completion event is set.</para>
5542     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
5543     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
5544     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
5545     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
5546     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
5547     ///     and not when the lamda returns.</para>
5548     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
5549     ///     without the need for locks.</para>
5550     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
5551     ///     to Windows Store apps.</para>
5552     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5553     /// </remarks>
5554     /**/
5555     template<typename _Ty>
5556     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5557         explicit task(_Ty _Param)
5558     {
5559         details::_ValidateTaskConstructorArgs<void, _Ty>(_Param);
5560 
5561         _M_unitTask._CreateImpl(Concurrency::cancellation_token::none()._GetImplValue());
5562         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of the task constructor.
5563         _M_unitTask._SetTaskCreationAddressHint(_ReturnAddress());
5564 
5565         _TaskInitMaybeFunctor(_Param, details::_IsCallable<void>(_Param, 0, 0, 0));
5566     }
5567 #endif
5568     /// <summary>
5569     ///     Constructs a <c>task</c> object.
5570     /// </summary>
5571     /// <typeparam name="_Ty">
5572     ///     The type of the parameter from which the task is to be constructed.
5573     /// </typeparam>
5574     /// <param name="_Param">
5575     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a <c>task_completion_event&lt;result_type&gt;</c>
5576     ///     object, or a Windows::Foundation::IAsyncInfo if you are using tasks in your Windows Store app. The lambda or function
5577     ///     object should be a type equivalent to <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
5578     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
5579     /// </param>
5580     /// <param name="_Token">
5581     ///     The cancellation token to associate with this task. A task created without a cancellation token cannot be canceled. It implicitly receives
5582     ///     the token <c>cancellation_token::none()</c>.
5583     /// </param>
5584     /// <remarks>
5585     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
5586     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
5587     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
5588     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
5589     ///     completion event is set.</para>
5590     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
5591     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
5592     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
5593     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
5594     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
5595     ///     and not when the lamda returns.</para>
5596     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
5597     ///     without the need for locks.</para>
5598     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
5599     ///     to Windows Store apps.</para>
5600     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5601     /// </remarks>
5602     /**/
5603     template<typename _Ty>
5604     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5605 #if _MSC_VER >= 1800
5606         explicit task(_Ty _Param, const task_options& _TaskOptions = task_options())
5607 #else
5608         explicit task(_Ty _Param, Concurrency::cancellation_token _CancellationToken)
5609 #endif
5610     {
5611             details::_ValidateTaskConstructorArgs<void, _Ty>(_Param);
5612 #if _MSC_VER >= 1800
5613             _M_unitTask._CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
5614 #else
5615             _M_unitTask._CreateImpl(_CancellationToken._GetImplValue());
5616 #endif
5617             // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of the task constructor.
5618 #if _MSC_VER >= 1800
5619             _M_unitTask._SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
5620 #else
5621             _M_unitTask._SetTaskCreationAddressHint(_ReturnAddress());
5622 #endif
5623             _TaskInitMaybeFunctor(_Param, details::_IsCallable<void>(_Param, 0, 0, 0));
5624         }
5625 
5626     /// <summary>
5627     ///     Constructs a <c>task</c> object.
5628     /// </summary>
5629     /// <param name="_Other">
5630     ///     The source <c>task</c> object.
5631     /// </param>
5632     /// <remarks>
5633     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
5634     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
5635     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
5636     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
5637     ///     completion event is set.</para>
5638     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
5639     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
5640     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
5641     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
5642     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
5643     ///     and not when the lamda returns.</para>
5644     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
5645     ///     without the need for locks.</para>
5646     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
5647     ///     to Windows Store apps.</para>
5648     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5649     /// </remarks>
5650     /**/
5651     task(const task& _Other) : _M_unitTask(_Other._M_unitTask){}
5652 
5653     /// <summary>
5654     ///     Constructs a <c>task</c> object.
5655     /// </summary>
5656     /// <param name="_Other">
5657     ///     The source <c>task</c> object.
5658     /// </param>
5659     /// <remarks>
5660     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within containers.
5661     ///     A default constructed task cannot be used until you assign a valid task to it. Methods such as <c>get</c>, <c>wait</c> or <c>then</c>
5662     ///     will throw an <see cref="invalid_argument Class">invalid_argument</see> exception when called on a default constructed task.
5663     ///     <para>A task that is created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the task
5664     ///     completion event is set.</para>
5665     ///     <para>The version of the constructor that takes a cancellation token creates a task that can be canceled using the
5666     ///     <c>cancellation_token_source</c> the token was obtained from. Tasks created without a cancellation token are not cancelable.</para>
5667     ///     <para>Tasks created from a <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
5668     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes. Similarly, tasks created
5669     ///     from a lamda that returns a <c>task&lt;result_type&gt;</c> reach their terminal state when the inner task reaches its terminal state,
5670     ///     and not when the lamda returns.</para>
5671     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by multiple threads
5672     ///     without the need for locks.</para>
5673     ///     <para>The constructor overloads that take a Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available
5674     ///     to Windows Store apps.</para>
5675     ///     <para>For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5676     /// </remarks>
5677     /**/
5678     task(task&& _Other) : _M_unitTask(std::move(_Other._M_unitTask)) {}
5679 
5680     /// <summary>
5681     ///     Replaces the contents of one <c>task</c> object with another.
5682     /// </summary>
5683     /// <param name="_Other">
5684     ///     The source <c>task</c> object.
5685     /// </param>
5686     /// <remarks>
5687     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents the same
5688     ///     actual task as <paramref name="_Other"/> does.
5689     /// </remarks>
5690     /**/
5691     task& operator=(const task& _Other)
5692     {
5693         if (this != &_Other)
5694         {
5695             _M_unitTask = _Other._M_unitTask;
5696         }
5697         return *this;
5698     }
5699 
5700     /// <summary>
5701     ///     Replaces the contents of one <c>task</c> object with another.
5702     /// </summary>
5703     /// <param name="_Other">
5704     ///     The source <c>task</c> object.
5705     /// </param>
5706     /// <remarks>
5707     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents the same
5708     ///     actual task as <paramref name="_Other"/> does.
5709     /// </remarks>
5710     /**/
5711     task& operator=(task&& _Other)
5712     {
5713         if (this != &_Other)
5714         {
5715             _M_unitTask = std::move(_Other._M_unitTask);
5716         }
5717         return *this;
5718     }
5719 #if _MSC_VER < 1800
5720     /// <summary>
5721     ///     Adds a continuation task to this task.
5722     /// </summary>
5723     /// <typeparam name="_Function">
5724     ///     The type of the function object that will be invoked by this task.
5725     /// </typeparam>
5726     /// <param name="_Func">
5727     ///     The continuation function to execute when this task completes. This continuation function must take as input
5728     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
5729     ///     of the result this task produces.
5730     /// </param>
5731     /// <returns>
5732     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
5733     /// </returns>
5734     /// <remarks>
5735     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
5736     ///     to Windows Store apps.
5737     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5738     /// </remarks>
5739     /**/
5740     template<typename _Function>
5741     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5742         auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5743     {
5744         auto _ContinuationTask = _M_unitTask._ThenImpl<void, _Function>(_Func, nullptr, task_continuation_context::use_default());
5745         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
5746         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
5747         return _ContinuationTask;
5748     }
5749 #endif
5750     /// <summary>
5751     ///     Adds a continuation task to this task.
5752     /// </summary>
5753     /// <typeparam name="_Function">
5754     ///     The type of the function object that will be invoked by this task.
5755     /// </typeparam>
5756     /// <param name="_Func">
5757     ///     The continuation function to execute when this task completes. This continuation function must take as input
5758     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
5759     ///     of the result this task produces.
5760     /// </param>
5761     /// <param name="_CancellationToken">
5762     ///     The cancellation token to associate with the continuation task. A continuation task that is created without a cancellation token will inherit
5763     ///     the token of its antecedent task.
5764     /// </param>
5765     /// <returns>
5766     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
5767     /// </returns>
5768     /// <remarks>
5769     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
5770     ///     to Windows Store apps.
5771     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5772     /// </remarks>
5773     /**/
5774     template<typename _Function>
5775     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5776 #if _MSC_VER >= 1800
5777     auto then(const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5778     {
5779         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
5780         return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
5781     }
5782 #else
5783     auto then(const _Function& _Func, Concurrency::cancellation_token _CancellationToken) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5784     {
5785         auto _ContinuationTask = _M_unitTask._ThenImpl<void, _Function>(_Func, _CancellationToken._GetImplValue(), task_continuation_context::use_default());
5786         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
5787         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
5788         return _ContinuationTask;
5789     }
5790     /// <summary>
5791     ///     Adds a continuation task to this task.
5792     /// </summary>
5793     /// <typeparam name="_Function">
5794     ///     The type of the function object that will be invoked by this task.
5795     /// </typeparam>
5796     /// <param name="_Func">
5797     ///     The continuation function to execute when this task completes. This continuation function must take as input
5798     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
5799     ///     of the result this task produces.
5800     /// </param>
5801     /// <param name="_ContinuationContext">
5802     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
5803     ///     Windows Store app. For more information, see <see cref="task_continuation_context Class">task_continuation_context</see>
5804     /// </param>
5805     /// <returns>
5806     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
5807     /// </returns>
5808     /// <remarks>
5809     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
5810     ///     to Windows Store apps.
5811     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5812     /// </remarks>
5813     /**/
5814     template<typename _Function>
5815     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5816         auto then(const _Function& _Func, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5817     {
5818         auto _ContinuationTask = _M_unitTask._ThenImpl<void, _Function>(_Func, nullptr, _ContinuationContext);
5819         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
5820         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
5821         return _ContinuationTask;
5822 
5823     }
5824 #endif
5825     /// <summary>
5826     ///     Adds a continuation task to this task.
5827     /// </summary>
5828     /// <typeparam name="_Function">
5829     ///     The type of the function object that will be invoked by this task.
5830     /// </typeparam>
5831     /// <param name="_Func">
5832     ///     The continuation function to execute when this task completes. This continuation function must take as input
5833     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the type
5834     ///     of the result this task produces.
5835     /// </param>
5836     /// <param name="_CancellationToken">
5837     ///     The cancellation token to associate with the continuation task. A continuation task that is created without a cancellation token will inherit
5838     ///     the token of its antecedent task.
5839     /// </param>
5840     /// <param name="_ContinuationContext">
5841     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
5842     ///     Windows Store app. For more information, see <see cref="task_continuation_context Class">task_continuation_context</see>
5843     /// </param>
5844     /// <returns>
5845     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref name="_Func"/> returns.
5846     /// </returns>
5847     /// <remarks>
5848     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo interface, are only available
5849     ///     to Windows Store apps.
5850     ///     <para>For more information on how to use task continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
5851     /// </remarks>
5852     /**/
5853     template<typename _Function>
5854     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
5855 #if _MSC_VER >= 1800
5856     auto then(const _Function& _Func, Concurrency::cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5857     {
5858         task_options _TaskOptions(_CancellationToken, _ContinuationContext);
5859         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
5860         return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
5861     }
5862 #else
5863     auto then(const _Function& _Func, Concurrency::cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
5864     {
5865         auto _ContinuationTask = _M_unitTask._ThenImpl<void, _Function>(_Func, _CancellationToken._GetImplValue(), _ContinuationContext);
5866         // Do not move the next line out of this function. It is important that _ReturnAddress() evaluate to the the call site of then.
5867         _ContinuationTask._SetTaskCreationAddressHint(_ReturnAddress());
5868         return _ContinuationTask;
5869     }
5870 #endif
5871 
5872     /// <summary>
5873     ///     Waits for this task to reach a terminal state. It is possible for <c>wait</c> to execute the task inline, if all of the tasks
5874     ///     dependencies are satisfied, and it has not already been picked up for execution by a background worker.
5875     /// </summary>
5876     /// <returns>
5877     ///     A <c>task_status</c> value which could be either <c>completed</c> or <c>canceled</c>. If the task encountered an exception
5878     ///     during execution, or an exception was propagated to it from an antecedent task, <c>wait</c> will throw that exception.
5879     /// </returns>
5880     /**/
5881     task_status wait() const
5882     {
5883         return _M_unitTask.wait();
5884     }
5885 
5886     /// <summary>
5887     ///     Returns the result this task produced. If the task is not in a terminal state, a call to <c>get</c> will wait for the task to
5888     ///     finish. This method does not return a value when called on a task with a <c>result_type</c> of <c>void</c>.
5889     /// </summary>
5890     /// <remarks>
5891     ///     If the task is canceled, a call to <c>get</c> will throw a <see cref="task_canceled Class">task_canceled</see> exception. If the task
5892     ///     encountered an different exception or an exception was propagated to it from an antecedent task, a call to <c>get</c> will throw that exception.
5893     /// </remarks>
5894     /**/
5895     void get() const
5896     {
5897         _M_unitTask.get();
5898     }
5899 #if _MSC_VER >= 1800
5900 
5901     /// <summary>
5902     ///     Determines if the task is completed.
5903     /// </summary>
5904     /// <returns>
5905     ///     True if the task has completed, false otherwise.
5906     /// </returns>
5907     /// <remarks>
5908     ///     The function returns true if the task is completed or canceled (with or without user exception).
5909     /// </remarks>
5910     bool is_done() const
5911     {
5912         return _M_unitTask.is_done();
5913     }
5914 
5915     /// <summary>
5916     ///     Returns the scheduler for this task
5917     /// </summary>
5918     /// <returns>
5919     ///     A pointer to the scheduler
5920     /// </returns>
5921     Concurrency::scheduler_ptr scheduler() const
5922     {
5923         return _M_unitTask.scheduler();
5924     }
5925 #endif
5926     /// <summary>
5927     ///     Determines whether the task unwraps a Windows Runtime <c>IAsyncInfo</c> interface or is descended from such a task.
5928     /// </summary>
5929     /// <returns>
5930     ///     <c>true</c> if the task unwraps an <c>IAsyncInfo</c> interface or is descended from such a task, <c>false</c> otherwise.
5931     /// </returns>
5932     /**/
5933     bool is_apartment_aware() const
5934     {
5935         return _M_unitTask.is_apartment_aware();
5936     }
5937 
5938     /// <summary>
5939     ///     Determines whether two <c>task</c> objects represent the same internal task.
5940     /// </summary>
5941     /// <returns>
5942     ///     <c>true</c> if the objects refer to the same underlying task, and <c>false</c> otherwise.
5943     /// </returns>
5944     /**/
5945     bool operator==(const task<void>& _Rhs) const
5946     {
5947         return (_M_unitTask == _Rhs._M_unitTask);
5948     }
5949 
5950     /// <summary>
5951     ///     Determines whether two <c>task</c> objects represent different internal tasks.
5952     /// </summary>
5953     /// <returns>
5954     ///     <c>true</c> if the objects refer to different underlying tasks, and <c>false</c> otherwise.
5955     /// </returns>
5956     /**/
5957     bool operator!=(const task<void>& _Rhs) const
5958     {
5959         return !operator==(_Rhs);
5960     }
5961 
5962     /// <summary>
5963     ///     Create an underlying task implementation.
5964     /// </summary>
5965 #if _MSC_VER >= 1800
5966     void _CreateImpl(Concurrency::details::_CancellationTokenState * _Ct, Concurrency::scheduler_ptr _Scheduler)
5967     {
5968         _M_unitTask._CreateImpl(_Ct, _Scheduler);
5969     }
5970 #else
5971     void _CreateImpl(Concurrency::details::_CancellationTokenState * _Ct)
5972     {
5973         _M_unitTask._CreateImpl(_Ct);
5974     }
5975 #endif
5976 
5977     /// <summary>
5978     ///     Return the underlying implementation for this task.
5979     /// </summary>
5980     const details::_Task_ptr<details::_Unit_type>::_Type & _GetImpl() const
5981     {
5982         return _M_unitTask._M_Impl;
5983     }
5984 
5985     /// <summary>
5986     ///     Set the implementation of the task to be the supplied implementaion.
5987     /// </summary>
5988     void _SetImpl(const details::_Task_ptr<details::_Unit_type>::_Type & _Impl)
5989     {
5990         _M_unitTask._SetImpl(_Impl);
5991     }
5992 
5993     /// <summary>
5994     ///     Set the implementation of the task to be the supplied implementaion using a move instead of a copy.
5995     /// </summary>
5996     void _SetImpl(details::_Task_ptr<details::_Unit_type>::_Type && _Impl)
5997     {
5998         _M_unitTask._SetImpl(std::move(_Impl));
5999     }
6000 
6001     /// <summary>
6002     ///     Sets a property determining whether the task is apartment aware.
6003     /// </summary>
6004     void _SetAsync(bool _Async = true)
6005     {
6006         _M_unitTask._SetAsync(_Async);
6007     }
6008 
6009     /// <summary>
6010     ///     Sets a field in the task impl to the return address for calls to the task constructors and the then method.
6011     /// </summary>
6012 #if _MSC_VER >= 1800
6013     void _SetTaskCreationCallstack(const details::_TaskCreationCallstack &_callstack)
6014     {
6015         _M_unitTask._SetTaskCreationCallstack(_callstack);
6016     }
6017 #else
6018     void _SetTaskCreationAddressHint(void* _Address)
6019     {
6020         _M_unitTask._SetTaskCreationAddressHint(_Address);
6021     }
6022 #endif
6023 
6024     /// <summary>
6025     ///     An internal version of then that takes additional flags and executes the continuation inline. Used for runtime internal continuations only.
6026     /// </summary>
6027     template<typename _Function>
6028 #if _MSC_VER >= 1800
6029     auto _Then(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState,
6030         details::_TaskInliningMode _InliningMode = Concurrency::details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
6031     {
6032         // inherit from antecedent
6033         auto _Scheduler = _GetImpl()->_GetScheduler();
6034 
6035         return _M_unitTask._ThenImpl<void, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
6036     }
6037 #else
6038     auto _Then(const _Function& _Func, Concurrency::details::_CancellationTokenState *_PTokenState,
6039         bool _Aggregating, details::_TaskInliningMode _InliningMode = Concurrency::details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
6040     {
6041         return _M_unitTask._ThenImpl<void, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Aggregating, _InliningMode);
6042     }
6043 #endif
6044 
6045 private:
6046     template <typename T> friend class task;
6047     template <typename T> friend class task_completion_event;
6048 
6049     /// <summary>
6050     ///     Initializes a task using a task completion event.
6051     /// </summary>
6052     void _TaskInitNoFunctor(task_completion_event<void>& _Event)
6053     {
6054         _M_unitTask._TaskInitNoFunctor(_Event._M_unitEvent);
6055     }
6056     /// <summary>
6057     ///     Initializes a task using an asynchronous action IAsyncAction*
6058     /// </summary>
6059     void _TaskInitNoFunctor(ABI::Windows::Foundation::IAsyncAction* _AsyncAction)
6060     {
6061         _M_unitTask._TaskInitAsyncOp<details::_Unit_type>(Microsoft::WRL::Make<details::_IAsyncActionToAsyncOperationConverter>(_AsyncAction).Get());
6062     }
6063 
6064     /// <summary>
6065     ///     Initializes a task using an asynchronous action with progress IAsyncActionWithProgress<_P>*
6066     /// </summary>
6067     template<typename _P>
6068     void _TaskInitNoFunctor(ABI::Windows::Foundation::IAsyncActionWithProgress<_P>* _AsyncActionWithProgress)
6069     {
6070         _M_unitTask._TaskInitAsyncOp<details::_Unit_type>(Microsoft::WRL::Make<details::_IAsyncActionWithProgressToAsyncOperationConverter<_P>>(_AsyncActionWithProgress).Get());
6071     }
6072     /// <summary>
6073     ///     Initializes a task using a callable object.
6074     /// </summary>
6075     template<typename _Function>
6076     void _TaskInitMaybeFunctor(_Function & _Func, std::true_type)
6077     {
6078         _M_unitTask._TaskInitWithFunctor<void, _Function>(_Func);
6079     }
6080 
6081     /// <summary>
6082     ///     Initializes a task using a non-callable object.
6083     /// </summary>
6084     template<typename _T>
6085     void _TaskInitMaybeFunctor(_T & _Param, std::false_type)
6086     {
6087         _TaskInitNoFunctor(_Param);
6088     }
6089 
6090     // The void task contains a task of a dummy type so common code can be used for tasks with void and non-void results.
6091     task<details::_Unit_type> _M_unitTask;
6092 };
6093 
6094 namespace details
6095 {
6096 
6097     /// <summary>
6098     ///   The following type traits are used for the create_task function.
6099     /// </summary>
6100 
6101     // Unwrap task<T>
6102     template<typename _Ty>
6103     _Ty _GetUnwrappedType(task<_Ty>);
6104 
6105     // Unwrap all supported types
6106     template<typename _Ty>
6107     auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg));
6108     // fallback
6109     template<typename _Ty>
6110     _Ty _GetUnwrappedReturnType(_Ty, ...);
6111 
6112     /// <summary>
6113     ///   <c>_GetTaskType</c> functions will retrieve task type <c>T</c> in <c>task[T](Arg)</c>,
6114     ///   for given constructor argument <c>Arg</c> and its property "callable".
6115     ///   It will automatically unwrap argument to get the final return type if necessary.
6116     /// </summary>
6117 
6118     // Non-Callable
6119     template<typename _Ty>
6120     _Ty _GetTaskType(task_completion_event<_Ty>, std::false_type);
6121 
6122     // Non-Callable
6123     template<typename _Ty>
6124     auto _GetTaskType(_Ty _NonFunc, std::false_type) -> decltype(_GetUnwrappedType(_NonFunc));
6125 
6126     // Callable
6127     template<typename _Ty>
6128     auto _GetTaskType(_Ty _Func, std::true_type) -> decltype(_GetUnwrappedReturnType(stdx::declval<_FunctionTypeTraits<_Ty, void>::_FuncRetType>(), 0));
6129 
6130     // Special callable returns void
6131     void _GetTaskType(std::function<HRESULT()>, std::true_type);
6132     struct _BadArgType{};
6133 
6134     template<typename _ReturnType, typename _Ty>
6135     auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable<_ReturnType>(_Param, 0, 0, 0)));
6136 
6137     template<typename _ReturnType, typename _Ty>
6138     _BadArgType _FilterValidTaskType(_Ty _Param, ...);
6139 
6140     template<typename _ReturnType, typename _Ty>
6141     struct _TaskTypeFromParam
6142     {
6143         typedef decltype(_FilterValidTaskType<_ReturnType>(stdx::declval<_Ty>(), 0)) _Type;
6144     };
6145 }
6146 
6147 
6148 /// <summary>
6149 ///     Creates a PPL <see cref="task Class">task</c> object. <c>create_task</c> can be used anywhere you would have used a task constructor.
6150 ///     It is provided mainly for convenience, because it allows use of the <c>auto</c> keyword while creating tasks.
6151 /// </summary>
6152 /// <typeparam name="_Ty">
6153 ///     The type of the parameter from which the task is to be constructed.
6154 /// </typeparam>
6155 /// <param name="_Param">
6156 ///     The parameter from which the task is to be constructed. This could be a lambda or function object, a <c>task_completion_event</c>
6157 ///     object, a different <c>task</c> object, or a Windows::Foundation::IAsyncInfo interface if you are using tasks in your Windows Store app.
6158 /// </param>
6159 /// <returns>
6160 ///     A new task of type <c>T</c>, that is inferred from <paramref name="_Param"/>.
6161 /// </returns>
6162 /// <remarks>
6163 ///     The first overload behaves like a task constructor that takes a single parameter.
6164 ///     <para>The second overload associates the cancellation token provided with the newly created task. If you use this overload you are not
6165 ///     allowed to pass in a different <c>task</c> object as the first parameter.</para>
6166 ///     <para>The type of the returned task is inferred from the first parameter to the function. If <paramref name="_Param"/> is a <c>task_completion_event&lt;T&gt;</c>,
6167 ///     a <c>task&lt;T&gt;</c>, or a functor that returns either type <c>T</c> or <c>task&lt;T&gt;</c>, the type of the created task is <c>task&lt;T&gt;</c>.
6168 ///     <para>In a Windows Store app, if <paramref name="_Param"/> is of type Windows::Foundation::IAsyncOperation&ltT&gt^ or
6169 ///     Windows::Foundation::IAsyncOperationWithProgress&ltT,P&gt^, or a functor that returns either of those types, the created task will be of type <c>task&lt;T&gt;</c>.
6170 ///     If <paramref name="_Param"/> is of type Windows::Foundation::IAsyncAction^ or Windows::Foundation::IAsyncActionWithProgress&lt;P&gt;^, or a functor
6171 ///     that returns either of those types, the created task will have type <c>task&lt;void&gt;</c>.</para>
6172 /// </remarks>
6173 /// <seealso cref="task Class"/>
6174 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6175 /**/
6176 template<typename _ReturnType, typename _Ty>
6177 __declspec(noinline)
6178 #if _MSC_VER >= 1800
6179 auto create_task(_Ty _Param, task_options _TaskOptions = task_options()) -> task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type>
6180 #else
6181 auto create_task(_Ty _Param) -> task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type>
6182 #endif
6183 {
6184     static_assert(!std::is_same<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type, details::_BadArgType>::value,
6185         "incorrect argument for create_task; can be a callable object, an asynchronous operation, or a task_completion_event"
6186         );
6187 #if _MSC_VER >= 1800
6188     details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
6189     task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type> _CreatedTask(_Param, _TaskOptions);
6190 #else
6191     task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type> _CreatedTask(_Param);
6192     // Ideally we would like to forceinline create_task, but __forceinline does nothing on debug builds. Therefore, we ask for no inlining
6193     // and overwrite the creation address hint set by the task constructor. DO NOT REMOVE this next line from create_task. It is
6194     // essential that _ReturnAddress() evaluate to the instruction right after the call to create_task in client code.
6195     _CreatedTask._SetTaskCreationAddressHint(_ReturnAddress());
6196 #endif
6197     return _CreatedTask;
6198 }
6199 
6200 /// <summary>
6201 ///     Creates a PPL <see cref="task Class">task</c> object. <c>create_task</c> can be used anywhere you would have used a task constructor.
6202 ///     It is provided mainly for convenience, because it allows use of the <c>auto</c> keyword while creating tasks.
6203 /// </summary>
6204 /// <typeparam name="_Ty">
6205 ///     The type of the parameter from which the task is to be constructed.
6206 /// </typeparam>
6207 /// <param name="_Param">
6208 ///     The parameter from which the task is to be constructed. This could be a lambda or function object, a <c>task_completion_event</c>
6209 ///     object, a different <c>task</c> object, or a Windows::Foundation::IAsyncInfo interface if you are using tasks in your Windows Store app.
6210 /// </param>
6211 /// <param name="_Token">
6212 ///     The cancellation token to associate with the task. When the source for this token is canceled, cancellation will be requested on the task.
6213 /// </param>
6214 /// <returns>
6215 ///     A new task of type <c>T</c>, that is inferred from <paramref name="_Param"/>.
6216 /// </returns>
6217 /// <remarks>
6218 ///     The first overload behaves like a task constructor that takes a single parameter.
6219 ///     <para>The second overload associates the cancellation token provided with the newly created task. If you use this overload you are not
6220 ///     allowed to pass in a different <c>task</c> object as the first parameter.</para>
6221 ///     <para>The type of the returned task is inferred from the first parameter to the function. If <paramref name="_Param"/> is a <c>task_completion_event&lt;T&gt;</c>,
6222 ///     a <c>task&lt;T&gt;</c>, or a functor that returns either type <c>T</c> or <c>task&lt;T&gt;</c>, the type of the created task is <c>task&lt;T&gt;</c>.
6223 ///     <para>In a Windows Store app, if <paramref name="_Param"/> is of type Windows::Foundation::IAsyncOperation&ltT&gt^ or
6224 ///     Windows::Foundation::IAsyncOperationWithProgress&ltT,P&gt^, or a functor that returns either of those types, the created task will be of type <c>task&lt;T&gt;</c>.
6225 ///     If <paramref name="_Param"/> is of type Windows::Foundation::IAsyncAction^ or Windows::Foundation::IAsyncActionWithProgress&lt;P&gt;^, or a functor
6226 ///     that returns either of those types, the created task will have type <c>task&lt;void&gt;</c>.</para>
6227 /// </remarks>
6228 /// <seealso cref="task Class"/>
6229 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6230 /**/
6231 #if _MSC_VER >= 1800
6232 template<typename _ReturnType>
6233 __declspec(noinline)
6234 task<_ReturnType> create_task(const task<_ReturnType>& _Task)
6235 {
6236     task<_ReturnType> _CreatedTask(_Task);
6237     return _CreatedTask;
6238 }
6239 #else
6240 template<typename _ReturnType, typename _Ty>
6241 __declspec(noinline)
6242 auto create_task(_Ty _Param, Concurrency::cancellation_token _Token) -> task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type>
6243 {
6244     static_assert(!std::is_same<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type, details::_BadArgType>::value,
6245         "incorrect argument for create_task; can be a callable object, an asynchronous operation, or a task_completion_event"
6246         );
6247     task<typename details::_TaskTypeFromParam<_ReturnType, _Ty>::_Type> _CreatedTask(_Param, _Token);
6248     // Ideally we would like to forceinline create_task, but __forceinline does nothing on debug builds. Therefore, we ask for no inlining
6249     // and overwrite the creation address hint set by the task constructor. DO NOT REMOVE this next line from create_task. It is
6250     // essential that _ReturnAddress() evaluate to the instruction right after the call to create_task in client code.
6251     _CreatedTask._SetTaskCreationAddressHint(_ReturnAddress());
6252     return _CreatedTask;
6253 }
6254 #endif
6255 
6256 namespace details
6257 {
6258     template<typename _T>
6259     task<typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperation<_T>*>()))>::type> _To_task_helper(ABI::Windows::Foundation::IAsyncOperation<_T>* op)
6260     {
6261         return task<_T>(op);
6262     }
6263 
6264     template<typename _T, typename _Progress>
6265     task<typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressSelector(stdx::declval<ABI::Windows::Foundation::IAsyncOperationWithProgress<_T, _Progress>*>()))>::type> _To_task_helper(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T, _Progress>* op)
6266     {
6267         return task<_T>(op);
6268     }
6269 
6270     inline task<void> _To_task_helper(ABI::Windows::Foundation::IAsyncAction* op)
6271     {
6272         return task<void>(op);
6273     }
6274 
6275     template<typename _Progress>
6276     task<void> _To_task_helper(ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>* op)
6277     {
6278         return task<void>(op);
6279     }
6280 
6281     template<typename _ProgressType>
6282     class _ProgressDispatcherBase
6283     {
6284     public:
6285 
6286         virtual ~_ProgressDispatcherBase()
6287         {
6288         }
6289 
6290         virtual void _Report(const _ProgressType& _Val) = 0;
6291     };
6292 
6293     template<typename _ProgressType, typename _ClassPtrType>
6294     class _ProgressDispatcher : public _ProgressDispatcherBase<_ProgressType>
6295     {
6296     public:
6297 
6298         virtual ~_ProgressDispatcher()
6299         {
6300         }
6301 
6302         _ProgressDispatcher(_ClassPtrType _Ptr) : _M_ptr(_Ptr)
6303         {
6304         }
6305 
6306         virtual void _Report(const _ProgressType& _Val)
6307         {
6308             _M_ptr->_FireProgress(_Val);
6309         }
6310 
6311     private:
6312 
6313         _ClassPtrType _M_ptr;
6314     };
6315 } // namespace details
6316 
6317 
6318 /// <summary>
6319 ///     The progress reporter class allows reporting progress notifications of a specific type. Each progress_reporter object is bound
6320 ///     to a particular asynchronous action or operation.
6321 /// </summary>
6322 /// <typeparam name="_ProgressType">
6323 ///     The payload type of each progress notification reported through the progress reporter.
6324 /// </typeparam>
6325 /// <remarks>
6326 ///     This type is only available to Windows Store apps.
6327 /// </remarks>
6328 /// <seealso cref="create_async Function"/>
6329 /**/
6330 template<typename _ProgressType>
6331 class progress_reporter
6332 {
6333     typedef std::shared_ptr<details::_ProgressDispatcherBase<_ProgressType>> _PtrType;
6334 
6335 public:
6336 
6337     /// <summary>
6338     ///     Sends a progress report to the asynchronous action or operation to which this progress reporter is bound.
6339     /// </summary>
6340     /// <param name="_Val">
6341     ///     The payload to report through a progress notification.
6342     /// </param>
6343     /**/
6344     void report(const _ProgressType& _Val) const
6345     {
6346         _M_dispatcher->_Report(_Val);
6347     }
6348 
6349     template<typename _ClassPtrType>
6350     static progress_reporter _CreateReporter(_ClassPtrType _Ptr)
6351     {
6352         progress_reporter _Reporter;
6353         details::_ProgressDispatcherBase<_ProgressType> *_PDispatcher = new details::_ProgressDispatcher<_ProgressType, _ClassPtrType>(_Ptr);
6354         _Reporter._M_dispatcher = _PtrType(_PDispatcher);
6355         return _Reporter;
6356     }
6357     progress_reporter() {}
6358 
6359 private:
6360     progress_reporter(details::_ProgressReporterCtorArgType);
6361 
6362     _PtrType _M_dispatcher;
6363 };
6364 
6365 namespace details
6366 {
6367     //
6368     // maps internal definitions for AsyncStatus and defines states that are not client visible
6369     //
6370     enum _AsyncStatusInternal
6371     {
6372         _AsyncCreated = -1,  // externally invisible
6373         // client visible states (must match AsyncStatus exactly)
6374         _AsyncStarted = ABI::Windows::Foundation::AsyncStatus::Started, // 0
6375         _AsyncCompleted = ABI::Windows::Foundation::AsyncStatus::Completed, // 1
6376         _AsyncCanceled = ABI::Windows::Foundation::AsyncStatus::Canceled, // 2
6377         _AsyncError = ABI::Windows::Foundation::AsyncStatus::Error, // 3
6378         // non-client visible internal states
6379         _AsyncCancelPending,
6380         _AsyncClosed,
6381         _AsyncUndefined
6382     };
6383 
6384     //
6385     // designates whether the "GetResults" method returns a single result (after complete fires) or multiple results
6386     // (which are progressively consumable between Start state and before Close is called)
6387     //
6388     enum _AsyncResultType
6389     {
6390         SingleResult = 0x0001,
6391         MultipleResults = 0x0002
6392     };
6393 
6394     template<typename _T>
6395     struct _ProgressTypeTraits
6396     {
6397         static const bool _TakesProgress = false;
6398         typedef void _ProgressType;
6399     };
6400 
6401     template<typename _T>
6402     struct _ProgressTypeTraits<progress_reporter<_T>>
6403     {
6404         static const bool _TakesProgress = true;
6405         typedef typename _T _ProgressType;
6406     };
6407 
6408     template<typename _T, bool bTakesToken = std::is_same<_T, Concurrency::cancellation_token>::value, bool bTakesProgress = _ProgressTypeTraits<_T>::_TakesProgress>
6409     struct _TokenTypeTraits
6410     {
6411         static const bool _TakesToken = false;
6412         typedef typename _T _ReturnType;
6413     };
6414 
6415     template<typename _T>
6416     struct _TokenTypeTraits<_T, false, true>
6417     {
6418         static const bool _TakesToken = false;
6419         typedef void _ReturnType;
6420     };
6421 
6422     template<typename _T>
6423     struct _TokenTypeTraits<_T, true, false>
6424     {
6425         static const bool _TakesToken = true;
6426         typedef void _ReturnType;
6427     };
6428 
6429     template<typename _T, size_t count = _FunctorTypeTraits<_T>::_ArgumentCount>
6430     struct _CAFunctorOptions
6431     {
6432         static const bool _TakesProgress = false;
6433         static const bool _TakesToken = false;
6434         typedef void _ProgressType;
6435         typedef void _ReturnType;
6436     };
6437 
6438     template<typename _T>
6439     struct _CAFunctorOptions<_T, 1>
6440     {
6441     private:
6442 
6443         typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
6444 
6445     public:
6446 
6447         static const bool _TakesProgress = _ProgressTypeTraits<_Argument1Type>::_TakesProgress;
6448         static const bool _TakesToken = _TokenTypeTraits<_Argument1Type>::_TakesToken;
6449         typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
6450         typedef typename _TokenTypeTraits<_Argument1Type>::_ReturnType _ReturnType;
6451     };
6452 
6453     template<typename _T>
6454     struct _CAFunctorOptions<_T, 2>
6455     {
6456     private:
6457 
6458         typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
6459         typedef typename _FunctorTypeTraits<_T>::_Argument2Type _Argument2Type;
6460 
6461     public:
6462 
6463         static const bool _TakesProgress = _ProgressTypeTraits<_Argument1Type>::_TakesProgress;
6464         static const bool _TakesToken = !_TakesProgress ? true : _TokenTypeTraits<_Argument2Type>::_TakesToken;
6465         typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
6466         typedef typename _TokenTypeTraits<_Argument2Type>::_ReturnType _ReturnType;
6467     };
6468 
6469     template<typename _T>
6470     struct _CAFunctorOptions<_T, 3>
6471     {
6472     private:
6473 
6474         typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
6475 
6476     public:
6477 
6478         static const bool _TakesProgress = true;
6479         static const bool _TakesToken = true;
6480         typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
6481         typedef typename _FunctorTypeTraits<_T>::_Argument3Type _ReturnType;
6482     };
6483 
6484     class _Zip
6485     {
6486     };
6487 
6488     // ***************************************************************************
6489     // Async Operation Task Generators
6490     //
6491 
6492     //
6493     // Functor returns an IAsyncInfo - result needs to be wrapped in a task:
6494     //
6495     template<typename _AsyncSelector, typename _ReturnType>
6496     struct _SelectorTaskGenerator
6497     {
6498 #if _MSC_VER >= 1800
6499         template<typename _Function>
6500         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6501         {
6502             task_options _taskOptinos(_Cts.get_token());
6503             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6504             return task<_ReturnType>(_Func(_pRet), _taskOptinos);
6505         }
6506 
6507         template<typename _Function>
6508         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6509         {
6510             task_options _taskOptinos(_Cts.get_token());
6511             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6512             return task<_ReturnType>(_Func(_Cts.get_token(), _pRet), _taskOptinos);
6513         }
6514 
6515         template<typename _Function, typename _ProgressObject>
6516         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6517         {
6518             task_options _taskOptinos(_Cts.get_token());
6519             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6520             return task<_ReturnType>(_Func(_Progress, _pRet), _taskOptinos);
6521         }
6522 
6523         template<typename _Function, typename _ProgressObject>
6524         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6525         {
6526             task_options _taskOptinos(_Cts.get_token());
6527             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6528             return task<_ReturnType>(_Func(_Progress, _Cts.get_token(), _pRet), _taskOptinos);
6529         }
6530 #else
6531         template<typename _Function>
6532         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6533         {
6534             return task<_ReturnType>(_Func(_pRet), _Cts.get_token());
6535         }
6536 
6537         template<typename _Function>
6538         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6539         {
6540             return task<_ReturnType>(_Func(_Cts.get_token(), _pRet), _Cts.get_token());
6541         }
6542 
6543         template<typename _Function, typename _ProgressObject>
6544         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6545         {
6546             return task<_ReturnType>(_Func(_Progress, _pRet), _Cts.get_token());
6547         }
6548 
6549         template<typename _Function, typename _ProgressObject>
6550         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6551         {
6552             return task<_ReturnType>(_Func(_Progress, _Cts.get_token(), _pRet), _Cts.get_token());
6553         }
6554 #endif
6555     };
6556 
6557     template<typename _AsyncSelector>
6558     struct _SelectorTaskGenerator<_AsyncSelector, void>
6559     {
6560 #if _MSC_VER >= 1800
6561         template<typename _Function>
6562         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6563         {
6564             task_options _taskOptinos(_Cts.get_token());
6565             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6566             return task<void>(_Func(), _taskOptinos);
6567         }
6568 
6569         template<typename _Function>
6570         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6571         {
6572             task_options _taskOptinos(_Cts.get_token());
6573             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6574             return task<void>(_Func(_Cts.get_token()), _taskOptinos);
6575         }
6576 
6577         template<typename _Function, typename _ProgressObject>
6578         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6579         {
6580             task_options _taskOptinos(_Cts.get_token());
6581             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6582             return task<void>(_Func(_Progress), _taskOptinos);
6583         }
6584 
6585         template<typename _Function, typename _ProgressObject>
6586         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6587         {
6588             task_options _taskOptinos(_Cts.get_token());
6589             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6590             return task<void>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
6591         }
6592 #else
6593         template<typename _Function>
6594         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6595         {
6596             return task<void>(_Func(), _Cts.get_token());
6597         }
6598 
6599         template<typename _Function>
6600         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6601         {
6602             return task<void>(_Func(_Cts.get_token()), _Cts.get_token());
6603         }
6604 
6605         template<typename _Function, typename _ProgressObject>
6606         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6607         {
6608             return task<void>(_Func(_Progress), _Cts.get_token());
6609         }
6610 
6611         template<typename _Function, typename _ProgressObject>
6612         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6613         {
6614             return task<void>(_Func(_Progress, _Cts.get_token()), _Cts.get_token());
6615         }
6616 #endif
6617     };
6618 
6619 #if _MSC_VER < 1800
6620     // For create_async lambdas that return a (non-task) result, we oversubscriber the current task for the duration of the
6621     // lambda.
6622     struct _Task_generator_oversubscriber
6623     {
6624         _Task_generator_oversubscriber()
6625         {
6626             Concurrency::details::_Context::_Oversubscribe(true);
6627         }
6628 
6629         ~_Task_generator_oversubscriber()
6630         {
6631             Concurrency::details::_Context::_Oversubscribe(false);
6632         }
6633     };
6634 #endif
6635 
6636     //
6637     // Functor returns a result - it needs to be wrapped in a task:
6638     //
6639     template<typename _ReturnType>
6640     struct _SelectorTaskGenerator<details::_TypeSelectorNoAsync, _ReturnType>
6641     {
6642 #if _MSC_VER >= 1800
6643 
6644 #pragma warning(push)
6645 #pragma warning(disable: 4702)
6646         template<typename _Function>
6647         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6648         {
6649             task_options _taskOptinos(_Cts.get_token());
6650             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6651             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6652                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6653                 (_Oversubscriber);
6654                 HRESULT hr = _Func(_pRet);
6655                 retVal = _pRet;
6656                 return hr;
6657             }, _taskOptinos);
6658         }
6659 #pragma warning(pop)
6660 
6661         template<typename _Function>
6662         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6663         {
6664             task_options _taskOptinos(_Cts.get_token());
6665             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6666             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6667                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6668                 (_Oversubscriber);
6669                 HRESULT hr = _Func(_Cts.get_token(), _pRet);
6670                 retVal = _pRet;
6671                 return hr;
6672             }, _taskOptinos);
6673         }
6674 
6675         template<typename _Function, typename _ProgressObject>
6676         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6677         {
6678             task_options _taskOptinos(_Cts.get_token());
6679             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6680             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6681                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6682                 (_Oversubscriber);
6683                 HRESULT hr = _Func(_Progress, _pRet);
6684                 retVal = _pRet;
6685                 return hr;
6686             }, _taskOptinos);
6687         }
6688 
6689         template<typename _Function, typename _ProgressObject>
6690         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6691         {
6692             task_options _taskOptinos(_Cts.get_token());
6693             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6694             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6695                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6696                 (_Oversubscriber);
6697                 HRESULT hr = _Func(_Progress, _Cts.get_token(), _pRet);
6698                 retVal = _pRet;
6699                 return hr;
6700             }, _taskOptinos);
6701         }
6702 #else
6703         template<typename _Function>
6704         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6705         {
6706             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6707                 _Task_generator_oversubscriber _Oversubscriber;
6708                 HRESULT hr = _Func(_pRet);
6709                 retVal = _pRet;
6710                 return hr;
6711             }, _Cts.get_token());
6712         }
6713 
6714         template<typename _Function>
6715         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6716         {
6717             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6718                 _Task_generator_oversubscriber _Oversubscriber;
6719                 HRESULT hr = _Func(_Cts.get_token(), _pRet);
6720                 retVal = _pRet;
6721                 return hr;
6722             }, _Cts.get_token());
6723         }
6724 
6725         template<typename _Function, typename _ProgressObject>
6726         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6727         {
6728             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6729                 _Task_generator_oversubscriber _Oversubscriber;
6730                 HRESULT hr = _Func(_Progress, _pRet);
6731                 retVal = _pRet;
6732                 return hr;
6733             }, _Cts.get_token());
6734         }
6735 
6736         template<typename _Function, typename _ProgressObject>
6737         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6738         {
6739             return task<_ReturnType>([=](_ReturnType* retVal) -> HRESULT {
6740                 _Task_generator_oversubscriber _Oversubscriber;
6741                 HRESULT hr = _Func(_Progress, _Cts.get_token(), _pRet);
6742                 retVal = _pRet;
6743                 return hr;
6744             }, _Cts.get_token());
6745         }
6746 #endif
6747     };
6748 
6749     template<>
6750     struct _SelectorTaskGenerator<details::_TypeSelectorNoAsync, void>
6751     {
6752 #if _MSC_VER >= 1800
6753         template<typename _Function>
6754         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6755         {
6756             task_options _taskOptinos(_Cts.get_token());
6757             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6758             return task<void>([=]() -> HRESULT {
6759                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6760                 (_Oversubscriber);
6761                 return _Func();
6762             }, _taskOptinos);
6763         }
6764 
6765         template<typename _Function>
6766         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6767         {
6768             task_options _taskOptinos(_Cts.get_token());
6769             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6770             return task<void>([=]() -> HRESULT {
6771                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6772                 (_Oversubscriber);
6773                 return _Func(_Cts.get_token());
6774             }, _taskOptinos);
6775         }
6776 
6777         template<typename _Function, typename _ProgressObject>
6778         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6779         {
6780             task_options _taskOptinos(_Cts.get_token());
6781             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6782             return task<void>([=]() -> HRESULT {
6783                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6784                 (_Oversubscriber);
6785                 return _Func(_Progress);
6786             }, _taskOptinos);
6787         }
6788 
6789         template<typename _Function, typename _ProgressObject>
6790         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6791         {
6792             task_options _taskOptinos(_Cts.get_token());
6793             details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
6794             return task<void>([=]() -> HRESULT {
6795                 Concurrency::details::_Task_generator_oversubscriber_t _Oversubscriber;
6796                 (_Oversubscriber);
6797                 return _Func(_Progress, _Cts.get_token());
6798             }, _taskOptinos);
6799         }
6800 #else
6801         template<typename _Function>
6802         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6803         {
6804             return task<void>([=]() -> HRESULT {
6805                 _Task_generator_oversubscriber _Oversubscriber;
6806                 return _Func();
6807             }, _Cts.get_token());
6808         }
6809 
6810         template<typename _Function>
6811         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6812         {
6813             return task<void>([=]() -> HRESULT {
6814                 _Task_generator_oversubscriber _Oversubscriber;
6815                 return _Func(_Cts.get_token());
6816             }, _Cts.get_token());
6817         }
6818 
6819         template<typename _Function, typename _ProgressObject>
6820         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6821         {
6822             return task<void>([=]() -> HRESULT {
6823                 _Task_generator_oversubscriber _Oversubscriber;
6824                 return _Func(_Progress);
6825             }, _Cts.get_token());
6826         }
6827 
6828         template<typename _Function, typename _ProgressObject>
6829         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6830         {
6831             return task<void>([=]() -> HRESULT {
6832                 _Task_generator_oversubscriber _Oversubscriber;
6833                 return _Func(_Progress, _Cts.get_token());
6834             }, _Cts.get_token());
6835         }
6836 #endif
6837     };
6838 
6839     //
6840     // Functor returns a task - the task can directly be returned:
6841     //
6842     template<typename _ReturnType>
6843     struct _SelectorTaskGenerator<details::_TypeSelectorAsyncTask, _ReturnType>
6844     {
6845         template<typename _Function>
6846 #if _MSC_VER >= 1800
6847         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6848 #else
6849         static task<_ReturnType> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6850 #endif
6851         {
6852             task<_ReturnType> _task;
6853             _Func(&_task);
6854             return _task;
6855         }
6856 
6857         template<typename _Function>
6858 #if _MSC_VER >= 1800
6859         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6860 #else
6861         static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6862 #endif
6863         {
6864             task<_ReturnType> _task;
6865             _Func(_Cts.get_token(), &_task);
6866             return _task;
6867         }
6868 
6869         template<typename _Function, typename _ProgressObject>
6870 #if _MSC_VER >= 1800
6871         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6872 #else
6873         static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6874 #endif
6875         {
6876             task<_ReturnType> _task;
6877             _Func(_Progress, &_task);
6878             return _task;
6879         }
6880 
6881         template<typename _Function, typename _ProgressObject>
6882 #if _MSC_VER >= 1800
6883         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6884 #else
6885         static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6886 #endif
6887         {
6888             task<_ReturnType> _task;
6889             _Func(_Progress, _Cts.get_token(), &_task);
6890             return _task;
6891         }
6892     };
6893 
6894     template<>
6895     struct _SelectorTaskGenerator<details::_TypeSelectorAsyncTask, void>
6896     {
6897         template<typename _Function>
6898 #if _MSC_VER >= 1800
6899         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6900 #else
6901         static task<void> _GenerateTask_0(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6902 #endif
6903         {
6904             task<void> _task;
6905             _Func(&_task);
6906             return _task;
6907         }
6908 
6909         template<typename _Function>
6910 #if _MSC_VER >= 1800
6911         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6912 #else
6913         static task<void> _GenerateTask_1C(const _Function& _Func, Concurrency::cancellation_token_source _Cts)
6914 #endif
6915         {
6916             task<void> _task;
6917             _Func(_Cts.get_token(), &_task);
6918             return _task;
6919         }
6920 
6921         template<typename _Function, typename _ProgressObject>
6922 #if _MSC_VER >= 1800
6923         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6924 #else
6925         static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6926 #endif
6927         {
6928             task<void> _task;
6929             _Func(_Progress, &_task);
6930             return _task;
6931         }
6932 
6933         template<typename _Function, typename _ProgressObject>
6934 #if _MSC_VER >= 1800
6935         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6936 #else
6937         static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, Concurrency::cancellation_token_source _Cts)
6938 #endif
6939         {
6940             task<void> _task;
6941             _Func(_Progress, _Cts.get_token(), &_task);
6942             return _task;
6943         }
6944     };
6945 
6946     template<typename _Generator, bool _TakesToken, bool TakesProgress>
6947     struct _TaskGenerator
6948     {
6949     };
6950 
6951     template<typename _Generator>
6952     struct _TaskGenerator<_Generator, false, false>
6953     {
6954 #if _MSC_VER >= 1800
6955         template<typename _Function, typename _ClassPtr, typename _ProgressType>
6956         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6957             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
6958         {
6959             (void)_Ptr;
6960             return _Generator::_GenerateTask_0(_Func, _Cts, _callstack);
6961         }
6962 
6963         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
6964         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
6965             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet, _callstack))
6966         {
6967             return _Generator::_GenerateTask_0(_Func, _Cts, _pRet, _callstack);
6968         }
6969 #else
6970         template<typename _Function, typename _ClassPtr, typename _ProgressType>
6971         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
6972             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts))
6973         {
6974             (void)_Ptr;
6975             return _Generator::_GenerateTask_0(_Func, _Cts);
6976         }
6977 
6978         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
6979         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
6980             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet))
6981         {
6982             return _Generator::_GenerateTask_0(_Func, _Cts, _pRet);
6983         }
6984 #endif
6985     };
6986 
6987     template<typename _Generator>
6988     struct _TaskGenerator<_Generator, true, false>
6989     {
6990 #if _MSC_VER >= 1800
6991         template<typename _Function, typename _ClassPtr, typename _ProgressType>
6992         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
6993             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
6994         {
6995             return _Generator::_GenerateTask_1C(_Func, _Cts, _callstack);
6996         }
6997 
6998         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
6999         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7000             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet, _callstack))
7001         {
7002             return _Generator::_GenerateTask_1C(_Func, _Cts, _pRet, _callstack);
7003         }
7004 #else
7005         template<typename _Function, typename _ClassPtr, typename _ProgressType>
7006         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
7007             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts))
7008         {
7009             return _Generator::_GenerateTask_1C(_Func, _Cts);
7010         }
7011 
7012         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
7013         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7014             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet))
7015         {
7016             return _Generator::_GenerateTask_1C(_Func, _Cts, _pRet);
7017         }
7018 #endif
7019     };
7020 
7021     template<typename _Generator>
7022     struct _TaskGenerator<_Generator, false, true>
7023     {
7024 #if _MSC_VER >= 1800
7025         template<typename _Function, typename _ClassPtr, typename _ProgressType>
7026         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
7027             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
7028         {
7029             return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
7030         }
7031 
7032         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
7033         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7034             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet, _callstack))
7035         {
7036             return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _pRet, _callstack);
7037         }
7038 #else
7039         template<typename _Function, typename _ClassPtr, typename _ProgressType>
7040         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
7041             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts))
7042         {
7043             return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts);
7044         }
7045 
7046         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
7047         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7048             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet))
7049         {
7050             return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _pRet);
7051         }
7052 #endif
7053     };
7054 
7055     template<typename _Generator>
7056     struct _TaskGenerator<_Generator, true, true>
7057     {
7058 #if _MSC_VER >= 1800
7059         template<typename _Function, typename _ClassPtr, typename _ProgressType>
7060         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
7061             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
7062         {
7063             return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
7064         }
7065 
7066         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
7067         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7068             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet, _callstack))
7069         {
7070             return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _pRet, _callstack);
7071         }
7072 #else
7073         template<typename _Function, typename _ClassPtr, typename _ProgressType>
7074         static auto _GenerateTaskNoRet(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
7075             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts))
7076         {
7077             return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts);
7078         }
7079 
7080         template<typename _Function, typename _ClassPtr, typename _ProgressType, typename _ReturnType>
7081         static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7082             -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _pRet))
7083         {
7084             return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _pRet);
7085         }
7086 #endif
7087     };
7088 
7089     // ***************************************************************************
7090     // Async Operation Attributes Classes
7091     //
7092     // These classes are passed through the hierarchy of async base classes in order to hold multiple attributes of a given async construct in
7093     // a single container. An attribute class must define:
7094     //
7095     // Mandatory:
7096     // -------------------------
7097     //
7098     // _AsyncBaseType           : The Windows Runtime interface which is being implemented.
7099     // _CompletionDelegateType  : The Windows Runtime completion delegate type for the interface.
7100     // _ProgressDelegateType    : If _TakesProgress is true, the Windows Runtime progress delegate type for the interface. If it is false, an empty Windows Runtime type.
7101     // _ReturnType              : The return type of the async construct (void for actions / non-void for operations)
7102     //
7103     // _TakesProgress           : An indication as to whether or not
7104     //
7105     // _Generate_Task           : A function adapting the user's function into what's necessary to produce the appropriate task
7106     //
7107     // Optional:
7108     // -------------------------
7109     //
7110 
7111     template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken, bool _TakesProgress>
7112     struct _AsyncAttributes
7113     {
7114     };
7115 
7116     template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
7117     struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, true>
7118     {
7119         typedef typename ABI::Windows::Foundation::IAsyncOperationWithProgress<_ReturnType, _ProgressType> _AsyncBaseType;
7120         typedef typename ABI::Windows::Foundation::IAsyncOperationProgressHandler<_ReturnType, _ProgressType> _ProgressDelegateType;
7121         typedef typename ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<_ReturnType, _ProgressType> _CompletionDelegateType;
7122         typedef typename _ReturnType _ReturnType;
7123         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressSelector(stdx::declval<_AsyncBaseType*>()))>::type _ReturnType_abi;
7124         typedef typename _ProgressType _ProgressType;
7125         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationWithProgressProgressSelector(stdx::declval<_AsyncBaseType*>()))>::type _ProgressType_abi;
7126         typedef typename _TaskTraits::_AsyncKind _AsyncKind;
7127         typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
7128         typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
7129 
7130         static const bool _TakesProgress = true;
7131         static const bool _TakesToken = _TakesToken;
7132 
7133         template<typename _Function, typename _ClassPtr>
7134 #if _MSC_VER >= 1800
7135         static task<typename _TaskTraits::_TaskRetType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7136         {
7137             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType_abi, _ReturnType>(_Func, _Ptr, _Cts, _pRet, _callstack);
7138         }
7139 #else
7140         static task<typename _TaskTraits::_TaskRetType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7141         {
7142             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType_abi, _ReturnType>(_Func, _Ptr, _Cts, _pRet);
7143         }
7144 #endif
7145     };
7146 
7147     template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
7148     struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, false>
7149     {
7150         typedef typename ABI::Windows::Foundation::IAsyncOperation<_ReturnType> _AsyncBaseType;
7151         typedef _Zip _ProgressDelegateType;
7152         typedef typename ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_ReturnType> _CompletionDelegateType;
7153         typedef typename _ReturnType _ReturnType;
7154         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncOperationSelector(stdx::declval<_AsyncBaseType*>()))>::type _ReturnType_abi;
7155         typedef typename _TaskTraits::_AsyncKind _AsyncKind;
7156         typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
7157         typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
7158 
7159         static const bool _TakesProgress = false;
7160         static const bool _TakesToken = _TakesToken;
7161 
7162         template<typename _Function, typename _ClassPtr>
7163 #if _MSC_VER >= 1800
7164         static task<typename _TaskTraits::_TaskRetType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7165         {
7166             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType, _ReturnType>(_Func, _Ptr, _Cts, _pRet, _callstack);
7167         }
7168 #else
7169         static task<typename _TaskTraits::_TaskRetType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7170         {
7171             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType, _ReturnType>(_Func, _Ptr, _Cts, _pRet);
7172         }
7173 #endif
7174     };
7175 
7176     template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
7177     struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, true>
7178     {
7179         typedef typename ABI::Windows::Foundation::IAsyncActionWithProgress<_ProgressType> _AsyncBaseType;
7180         typedef typename ABI::Windows::Foundation::IAsyncActionProgressHandler<_ProgressType> _ProgressDelegateType;
7181         typedef typename ABI::Windows::Foundation::IAsyncActionWithProgressCompletedHandler<_ProgressType> _CompletionDelegateType;
7182         typedef void _ReturnType;
7183         typedef void _ReturnType_abi;
7184         typedef typename _ProgressType _ProgressType;
7185         typedef typename ABI::Windows::Foundation::Internal::GetAbiType<decltype(_UnwrapAsyncActionWithProgressSelector(stdx::declval<_AsyncBaseType*>()))>::type _ProgressType_abi;
7186         typedef typename _TaskTraits::_AsyncKind _AsyncKind;
7187         typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
7188         typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
7189 
7190         static const bool _TakesProgress = true;
7191         static const bool _TakesToken = _TakesToken;
7192 
7193 #if _MSC_VER >= 1800
7194         template<typename _Function, typename _ClassPtr>
7195         static task<void> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
7196         {
7197             return _TaskGenerator::_GenerateTaskNoRet<_Function, _ClassPtr, _ProgressType_abi>(_Func, _Ptr, _Cts, _callstack);
7198         }
7199         template<typename _Function, typename _ClassPtr>
7200         static task<task<void>> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7201         {
7202             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType_abi>(_Func, _Ptr, _Cts, _pRet, _callstack);
7203         }
7204 #else
7205         template<typename _Function, typename _ClassPtr>
7206         static task<void> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
7207         {
7208             return _TaskGenerator::_GenerateTaskNoRet<_Function, _ClassPtr, _ProgressType_abi>(_Func, _Ptr, _Cts);
7209         }
7210         template<typename _Function, typename _ClassPtr>
7211         static task<task<void>> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7212         {
7213             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType_abi>(_Func, _Ptr, _Cts, _pRet);
7214         }
7215 #endif
7216     };
7217 
7218     template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
7219     struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, false>
7220     {
7221         typedef typename ABI::Windows::Foundation::IAsyncAction _AsyncBaseType;
7222         typedef _Zip _ProgressDelegateType;
7223         typedef typename ABI::Windows::Foundation::IAsyncActionCompletedHandler _CompletionDelegateType;
7224         typedef void _ReturnType;
7225         typedef void _ReturnType_abi;
7226         typedef typename _TaskTraits::_AsyncKind _AsyncKind;
7227         typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
7228         typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
7229 
7230         static const bool _TakesProgress = false;
7231         static const bool _TakesToken = _TakesToken;
7232 
7233 #if _MSC_VER >= 1800
7234         template<typename _Function, typename _ClassPtr>
7235         static task<void> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
7236         {
7237             return _TaskGenerator::_GenerateTaskNoRet<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
7238         }
7239         template<typename _Function, typename _ClassPtr>
7240         static task<task<void>> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet, const _TaskCreationCallstack & _callstack)
7241         {
7242             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _pRet, _callstack);
7243         }
7244 #else
7245         template<typename _Function, typename _ClassPtr>
7246         static task<void> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts)
7247         {
7248             return _TaskGenerator::_GenerateTaskNoRet<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts);
7249         }
7250         template<typename _Function, typename _ClassPtr>
7251         static task<task<void>> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, Concurrency::cancellation_token_source _Cts, _ReturnType* _pRet)
7252         {
7253             return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _pRet);
7254         }
7255 #endif
7256     };
7257 
7258     template<typename _Function>
7259     struct _AsyncLambdaTypeTraits
7260     {
7261         typedef typename _Unhat<typename _CAFunctorOptions<_Function>::_ReturnType>::_Value _ReturnType;
7262         typedef typename _FunctorTypeTraits<_Function>::_Argument1Type _Argument1Type;
7263         typedef typename _CAFunctorOptions<_Function>::_ProgressType _ProgressType;
7264 
7265         static const bool _TakesProgress = _CAFunctorOptions<_Function>::_TakesProgress;
7266         static const bool _TakesToken = _CAFunctorOptions<_Function>::_TakesToken;
7267 
7268         typedef typename _TaskTypeTraits<_ReturnType> _TaskTraits;
7269         typedef typename _AsyncAttributes<_Function, _ProgressType, typename _TaskTraits::_TaskRetType, _TaskTraits, _TakesToken, _TakesProgress> _AsyncAttributes;
7270     };
7271     // ***************************************************************************
7272     // AsyncInfo (and completion) Layer:
7273     //
7274 #ifndef RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoBase_DEFINED
7275 #define RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoBase_DEFINED
7276     extern const __declspec(selectany) WCHAR RuntimeClass_Concurrency_winrt_details__AsyncInfoBase[] = L"Concurrency_winrt.details._AsyncInfoBase";
7277 #endif
7278 
7279     //
7280     // Internal base class implementation for async operations (based on internal Windows representation for ABI level async operations)
7281     //
7282     template < typename _Attributes, _AsyncResultType resultType = SingleResult >
7283     class _AsyncInfoBase abstract : public Microsoft::WRL::RuntimeClass<
7284         Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRt>, Microsoft::WRL::Implements<typename _Attributes::_AsyncBaseType, ABI::Windows::Foundation::IAsyncInfo>>
7285     {
7286         InspectableClass(RuntimeClass_Concurrency_winrt_details__AsyncInfoBase, BaseTrust)
7287     public:
7288         _AsyncInfoBase() :
7289             _M_currentStatus(_AsyncStatusInternal::_AsyncCreated),
7290             _M_errorCode(S_OK),
7291             _M_completeDelegate(nullptr),
7292             _M_CompleteDelegateAssigned(0),
7293             _M_CallbackMade(0)
7294         {
7295 #if _MSC_VER < 1800
7296             _M_id = Concurrency::details::_GetNextAsyncId();
7297 #else
7298             _M_id = Concurrency::details::platform::GetNextAsyncId();
7299 #endif
7300         }
7301     public:
7302         virtual STDMETHODIMP GetResults(typename _Attributes::_ReturnType_abi* results)
7303         {
7304             (void)results;
7305             return E_UNEXPECTED;
7306         }
7307 
7308         virtual STDMETHODIMP get_Id(unsigned int* id)
7309         {
7310             HRESULT hr = _CheckValidStateForAsyncInfoCall();
7311             if (FAILED(hr)) return hr;
7312             if (!id) return E_POINTER;
7313             *id = _M_id;
7314             return S_OK;
7315         }
7316 
7317         virtual STDMETHODIMP put_Id(unsigned int id)
7318         {
7319             HRESULT hr = _CheckValidStateForAsyncInfoCall();
7320             if (FAILED(hr)) return hr;
7321 
7322             if (id == 0)
7323             {
7324                 return E_INVALIDARG;
7325             }
7326             else if (_M_currentStatus != _AsyncStatusInternal::_AsyncCreated)
7327             {
7328                 return E_ILLEGAL_METHOD_CALL;
7329             }
7330 
7331             _M_id = id;
7332             return S_OK;
7333         }
7334         virtual STDMETHODIMP get_Status(ABI::Windows::Foundation::AsyncStatus* status)
7335         {
7336             HRESULT hr = _CheckValidStateForAsyncInfoCall();
7337             if (FAILED(hr)) return hr;
7338             if (!status) return E_POINTER;
7339 
7340             _AsyncStatusInternal _Current = _M_currentStatus;
7341             //
7342             // Map our internal cancel pending to cancelled. This way "pending cancelled" looks to the outside as "cancelled" but
7343             // can still transition to "completed" if the operation completes without acknowledging the cancellation request
7344             //
7345             switch (_Current)
7346             {
7347             case _AsyncCancelPending:
7348                 _Current = _AsyncCanceled;
7349                 break;
7350             case _AsyncCreated:
7351                 _Current = _AsyncStarted;
7352                 break;
7353             default:
7354                 break;
7355             }
7356 
7357             *status = static_cast<ABI::Windows::Foundation::AsyncStatus>(_Current);
7358             return S_OK;
7359         }
7360 
7361         virtual STDMETHODIMP get_ErrorCode(HRESULT* errorCode)
7362         {
7363             HRESULT hr = _CheckValidStateForAsyncInfoCall();
7364             if (FAILED(hr)) return hr;
7365             if (!hr) return hr;
7366             *errorCode = _M_errorCode;
7367             return S_OK;
7368         }
7369 
7370         virtual STDMETHODIMP get_Progress(typename _Attributes::_ProgressDelegateType** _ProgressHandler)
7371         {
7372             return _GetOnProgress(_ProgressHandler);
7373         }
7374 
7375         virtual STDMETHODIMP put_Progress(typename _Attributes::_ProgressDelegateType* _ProgressHandler)
7376         {
7377             return _PutOnProgress(_ProgressHandler);
7378         }
7379 
7380         virtual STDMETHODIMP Cancel()
7381         {
7382             if (_TransitionToState(_AsyncCancelPending))
7383             {
7384                 _OnCancel();
7385             }
7386             return S_OK;
7387         }
7388 
7389         virtual STDMETHODIMP Close()
7390         {
7391             if (_TransitionToState(_AsyncClosed))
7392             {
7393                 _OnClose();
7394             }
7395             else
7396             {
7397                 if (_M_currentStatus != _AsyncClosed) // Closed => Closed transition is just ignored
7398                 {
7399                     return E_ILLEGAL_STATE_CHANGE;
7400                 }
7401             }
7402             return S_OK;
7403         }
7404 
7405         virtual STDMETHODIMP get_Completed(typename _Attributes::_CompletionDelegateType** _CompleteHandler)
7406         {
7407             _CheckValidStateForDelegateCall();
7408             if (!_CompleteHandler) return E_POINTER;
7409             *_CompleteHandler = _M_completeDelegate.Get();
7410             return S_OK;
7411         }
7412 
7413         virtual STDMETHODIMP put_Completed(typename _Attributes::_CompletionDelegateType* _CompleteHandler)
7414         {
7415             _CheckValidStateForDelegateCall();
7416             // this delegate property is "write once"
7417             if (InterlockedIncrement(&_M_CompleteDelegateAssigned) == 1)
7418             {
7419                 _M_completeDelegateContext = _ContextCallback::_CaptureCurrent();
7420                 _M_completeDelegate = _CompleteHandler;
7421                 // Guarantee that the write of _M_completeDelegate is ordered with respect to the read of state below
7422                 // as perceived from _FireCompletion on another thread.
7423                 MemoryBarrier();
7424                 if (_IsTerminalState())
7425                 {
7426                     _FireCompletion();
7427                 }
7428             }
7429             else
7430             {
7431                 return E_ILLEGAL_DELEGATE_ASSIGNMENT;
7432             }
7433             return S_OK;
7434         }
7435 
7436     protected:
7437         // _Start - this is not externally visible since async operations "hot start" before returning to the caller
7438         STDMETHODIMP _Start()
7439         {
7440             if (_TransitionToState(_AsyncStarted))
7441             {
7442                 _OnStart();
7443             }
7444             else
7445             {
7446                 return E_ILLEGAL_STATE_CHANGE;
7447             }
7448             return S_OK;
7449         }
7450 
7451         HRESULT _FireCompletion()
7452         {
7453             HRESULT hr = S_OK;
7454             _TryTransitionToCompleted();
7455 
7456             // we guarantee that completion can only ever be fired once
7457             if (_M_completeDelegate != nullptr && InterlockedIncrement(&_M_CallbackMade) == 1)
7458             {
7459                 hr = _M_completeDelegateContext._CallInContext([=]() -> HRESULT {
7460                     ABI::Windows::Foundation::AsyncStatus status;
7461                     HRESULT hr;
7462                     if (SUCCEEDED(hr = this->get_Status(&status)))
7463                         _M_completeDelegate->Invoke((_Attributes::_AsyncBaseType*)this, status);
7464                     _M_completeDelegate = nullptr;
7465                     return hr;
7466                 });
7467             }
7468             return hr;
7469         }
7470 
7471         virtual STDMETHODIMP _GetOnProgress(typename _Attributes::_ProgressDelegateType** _ProgressHandler)
7472         {
7473             (void)_ProgressHandler;
7474             return E_UNEXPECTED;
7475         }
7476 
7477         virtual STDMETHODIMP _PutOnProgress(typename _Attributes::_ProgressDelegateType* _ProgressHandler)
7478         {
7479             (void)_ProgressHandler;
7480             return E_UNEXPECTED;
7481         }
7482 
7483 
7484         bool _TryTransitionToCompleted()
7485         {
7486             return _TransitionToState(_AsyncStatusInternal::_AsyncCompleted);
7487         }
7488 
7489         bool _TryTransitionToCancelled()
7490         {
7491             return _TransitionToState(_AsyncStatusInternal::_AsyncCanceled);
7492         }
7493 
7494         bool _TryTransitionToError(const HRESULT error)
7495         {
7496             _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_errorCode), error, S_OK);
7497             return _TransitionToState(_AsyncStatusInternal::_AsyncError);
7498         }
7499 
7500         // This method checks to see if the delegate properties can be
7501         // modified in the current state and generates the appropriate
7502         // error hr in the case of violation.
7503         inline HRESULT _CheckValidStateForDelegateCall()
7504         {
7505             if (_M_currentStatus == _AsyncClosed)
7506             {
7507                 return E_ILLEGAL_METHOD_CALL;
7508             }
7509             return S_OK;
7510         }
7511 
7512         // This method checks to see if results can be collected in the
7513         // current state and generates the appropriate error hr in
7514         // the case of a violation.
7515         inline HRESULT _CheckValidStateForResultsCall()
7516         {
7517             _AsyncStatusInternal _Current = _M_currentStatus;
7518 
7519             if (_Current == _AsyncError)
7520             {
7521                 return _M_errorCode;
7522             }
7523 #pragma warning(push)
7524 #pragma warning(disable: 4127) // Conditional expression is constant
7525             // single result illegal before transition to Completed or Cancelled state
7526             if (resultType == SingleResult)
7527 #pragma warning(pop)
7528             {
7529                 if (_Current != _AsyncCompleted)
7530                 {
7531                     return E_ILLEGAL_METHOD_CALL;
7532                 }
7533             }
7534             // multiple results can be called after Start has been called and before/after Completed
7535             else if (_Current != _AsyncStarted &&
7536                 _Current != _AsyncCancelPending &&
7537                 _Current != _AsyncCanceled &&
7538                 _Current != _AsyncCompleted)
7539             {
7540                 return E_ILLEGAL_METHOD_CALL;
7541             }
7542             return S_OK;
7543         }
7544 
7545         // This method can be called by derived classes periodically to determine
7546         // whether the asynchronous operation should continue processing or should
7547         // be halted.
7548         inline bool _ContinueAsyncOperation()
7549         {
7550             return _M_currentStatus == _AsyncStarted;
7551         }
7552 
7553         // These two methods are used to allow the async worker implementation do work on
7554         // state transitions. No real "work" should be done in these methods. In other words
7555         // they should not block for a long time on UI timescales.
7556         virtual void _OnStart() = 0;
7557         virtual void _OnClose() = 0;
7558         virtual void _OnCancel() = 0;
7559 
7560     private:
7561 
7562         // This method is used to check if calls to the AsyncInfo properties
7563         // (id, status, errorcode) are legal in the current state. It also
7564         // generates the appropriate error hr to return in the case of an
7565         // illegal call.
7566         inline HRESULT _CheckValidStateForAsyncInfoCall()
7567         {
7568             _AsyncStatusInternal _Current = _M_currentStatus;
7569             if (_Current == _AsyncClosed)
7570             {
7571                 return E_ILLEGAL_METHOD_CALL;
7572             }
7573             else if (_Current == _AsyncCreated)
7574             {
7575                 return E_ASYNC_OPERATION_NOT_STARTED;
7576             }
7577             return S_OK;
7578         }
7579 
7580         inline bool _TransitionToState(const _AsyncStatusInternal _NewState)
7581         {
7582             _AsyncStatusInternal _Current = _M_currentStatus;
7583 
7584             // This enforces the valid state transitions of the asynchronous worker object
7585             // state machine.
7586             switch (_NewState)
7587             {
7588             case _AsyncStatusInternal::_AsyncStarted:
7589                 if (_Current != _AsyncCreated)
7590                 {
7591                     return false;
7592                 }
7593                 break;
7594             case _AsyncStatusInternal::_AsyncCompleted:
7595                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
7596                 {
7597                     return false;
7598                 }
7599                 break;
7600             case _AsyncStatusInternal::_AsyncCancelPending:
7601                 if (_Current != _AsyncStarted)
7602                 {
7603                     return false;
7604                 }
7605                 break;
7606             case _AsyncStatusInternal::_AsyncCanceled:
7607                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
7608                 {
7609                     return false;
7610                 }
7611                 break;
7612             case _AsyncStatusInternal::_AsyncError:
7613                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
7614                 {
7615                     return false;
7616                 }
7617                 break;
7618             case _AsyncStatusInternal::_AsyncClosed:
7619                 if (!_IsTerminalState(_Current))
7620                 {
7621                     return false;
7622                 }
7623                 break;
7624             default:
7625                 return false;
7626                 break;
7627             }
7628 
7629             // attempt the transition to the new state
7630             // Note: if currentStatus_ == _Current, then there was no intervening write
7631             // by the async work object and the swap succeeded.
7632             _AsyncStatusInternal _RetState = static_cast<_AsyncStatusInternal>(
7633                 _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_currentStatus),
7634                 _NewState,
7635                 static_cast<LONG>(_Current)));
7636 
7637             // ICE returns the former state, if the returned state and the
7638             // state we captured at the beginning of this method are the same,
7639             // the swap succeeded.
7640             return (_RetState == _Current);
7641         }
7642 
7643         inline bool _IsTerminalState()
7644         {
7645             return _IsTerminalState(_M_currentStatus);
7646         }
7647 
7648         inline bool _IsTerminalState(_AsyncStatusInternal status)
7649         {
7650             return (status == _AsyncError ||
7651                 status == _AsyncCanceled ||
7652                 status == _AsyncCompleted ||
7653                 status == _AsyncClosed);
7654         }
7655 
7656     private:
7657 
7658         _ContextCallback        _M_completeDelegateContext;
7659         Microsoft::WRL::ComPtr<typename _Attributes::_CompletionDelegateType>  _M_completeDelegate; //ComPtr cannot be volatile as it does not have volatile accessors
7660         _AsyncStatusInternal volatile                   _M_currentStatus;
7661         HRESULT volatile                                _M_errorCode;
7662         unsigned int                                    _M_id;
7663         long volatile                                   _M_CompleteDelegateAssigned;
7664         long volatile                                   _M_CallbackMade;
7665     };
7666 
7667     // ***************************************************************************
7668     // Progress Layer (optional):
7669     //
7670 
7671     template< typename _Attributes, bool _HasProgress, _AsyncResultType _ResultType = SingleResult >
7672     class _AsyncProgressBase abstract : public _AsyncInfoBase<_Attributes, _ResultType>
7673     {
7674     };
7675 
7676     template< typename _Attributes, _AsyncResultType _ResultType>
7677     class _AsyncProgressBase<_Attributes, true, _ResultType> abstract : public _AsyncInfoBase<_Attributes, _ResultType>
7678     {
7679     public:
7680 
7681         _AsyncProgressBase() : _AsyncInfoBase<_Attributes, _ResultType>(),
7682             _M_progressDelegate(nullptr)
7683         {
7684         }
7685 
7686         virtual STDMETHODIMP _GetOnProgress(typename _Attributes::_ProgressDelegateType** _ProgressHandler) override
7687         {
7688             HRESULT hr = _CheckValidStateForDelegateCall();
7689             if (FAILED(hr)) return hr;
7690             *_ProgressHandler = _M_progressDelegate;
7691             return S_OK;
7692         }
7693 
7694         virtual STDMETHODIMP _PutOnProgress(typename _Attributes::_ProgressDelegateType* _ProgressHandler) override
7695         {
7696             HRESULT hr = _CheckValidStateForDelegateCall();
7697             if (FAILED(hr)) return hr;
7698             _M_progressDelegate = _ProgressHandler;
7699             _M_progressDelegateContext = _ContextCallback::_CaptureCurrent();
7700             return S_OK;
7701         }
7702 
7703     public:
7704 
7705         void _FireProgress(const typename _Attributes::_ProgressType_abi& _ProgressValue)
7706         {
7707             if (_M_progressDelegate != nullptr)
7708             {
7709                 _M_progressDelegateContext._CallInContext([=]() -> HRESULT {
7710                     _M_progressDelegate->Invoke((_Attributes::_AsyncBaseType*)this, _ProgressValue);
7711                     return S_OK;
7712                 });
7713             }
7714         }
7715 
7716     private:
7717 
7718         _ContextCallback _M_progressDelegateContext;
7719         typename _Attributes::_ProgressDelegateType* _M_progressDelegate;
7720     };
7721 
7722     template<typename _Attributes, _AsyncResultType _ResultType = SingleResult>
7723     class _AsyncBaseProgressLayer abstract : public _AsyncProgressBase<_Attributes, _Attributes::_TakesProgress, _ResultType>
7724     {
7725     };
7726 
7727     // ***************************************************************************
7728     // Task Adaptation Layer:
7729     //
7730 
7731     //
7732     // _AsyncTaskThunkBase provides a bridge between IAsync<Action/Operation> and task.
7733     //
7734     template<typename _Attributes, typename _ReturnType>
7735     class _AsyncTaskThunkBase abstract : public _AsyncBaseProgressLayer<_Attributes>
7736     {
7737     public:
7738 
7739         //AsyncAction*
7740         virtual STDMETHODIMP GetResults()
7741         {
7742             HRESULT hr = _CheckValidStateForResultsCall();
7743             if (FAILED(hr)) return hr;
7744             _M_task.get();
7745             return S_OK;
7746         }
7747     public:
7748         typedef task<_ReturnType> _TaskType;
7749 
7750         _AsyncTaskThunkBase(const _TaskType& _Task)
7751             : _M_task(_Task)
7752         {
7753         }
7754 
7755         _AsyncTaskThunkBase()
7756         {
7757         }
7758 #if _MSC_VER < 1800
7759         void _SetTaskCreationAddressHint(void* _SourceAddressHint)
7760         {
7761             if (!(std::is_same<_Attributes::_AsyncKind, _TypeSelectorAsyncTask>::value))
7762             {
7763                 // Overwrite the creation address with the return address of create_async unless the
7764                 // lambda returned a task. If the create async lambda returns a task, that task is reused and
7765                 // we want to preserve its creation address hint.
7766                 _M_task._SetTaskCreationAddressHint(_SourceAddressHint);
7767             }
7768         }
7769 #endif
7770     protected:
7771         virtual void _OnStart() override
7772         {
7773             _M_task.then([=](_TaskType _Antecedent) -> HRESULT {
7774                 try
7775                 {
7776                     _Antecedent.get();
7777                 }
7778                 catch (Concurrency::task_canceled&)
7779                 {
7780                     _TryTransitionToCancelled();
7781                 }
7782                 catch (IRestrictedErrorInfo*& _Ex)
7783                 {
7784                     HRESULT hr;
7785                     HRESULT _hr;
7786                     hr = _Ex->GetErrorDetails(NULL, &_hr, NULL, NULL);
7787                     if (SUCCEEDED(hr)) hr = _hr;
7788                     _TryTransitionToError(hr);
7789                 }
7790                 catch (...)
7791                 {
7792                     _TryTransitionToError(E_FAIL);
7793                 }
7794                 return _FireCompletion();
7795             });
7796         }
7797 
7798     protected:
7799         _TaskType _M_task;
7800         Concurrency::cancellation_token_source _M_cts;
7801     };
7802 
7803     template<typename _Attributes, typename _ReturnType, typename _Return>
7804     class _AsyncTaskReturn abstract : public _AsyncTaskThunkBase<_Attributes, _Return>
7805     {
7806     public:
7807         //AsyncOperation*
7808         virtual STDMETHODIMP GetResults(_ReturnType* results)
7809         {
7810             HRESULT hr = _CheckValidStateForResultsCall();
7811             if (FAILED(hr)) return hr;
7812             _M_task.get();
7813             *results = _M_results;
7814             return S_OK;
7815         }
7816         template <typename _Function>
7817 #if _MSC_VER >= 1800
7818         void DoCreateTask(_Function _func, const _TaskCreationCallstack & _callstack)
7819         {
7820             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts, &_M_results, _callstack);
7821         }
7822 #else
7823         void DoCreateTask(_Function _func)
7824         {
7825             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts, &_M_results);
7826         }
7827 #endif
7828     protected:
7829         _ReturnType _M_results;
7830     };
7831 
7832     template<typename _Attributes, typename _ReturnType>
7833     class _AsyncTaskReturn<_Attributes, _ReturnType, void> abstract : public _AsyncTaskThunkBase<_Attributes, void>
7834     {
7835     public:
7836         template <typename _Function>
7837 #if _MSC_VER >= 1800
7838         void DoCreateTask(_Function _func, const _TaskCreationCallstack & _callstack)
7839         {
7840             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts, _callstack);
7841         }
7842 #else
7843         void DoCreateTask(_Function _func)
7844         {
7845             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts);
7846         }
7847 #endif
7848     };
7849 
7850     template<typename _Attributes>
7851     class _AsyncTaskReturn<_Attributes, void, task<void>> abstract : public _AsyncTaskThunkBase<_Attributes, task<void>>
7852     {
7853     public:
7854         template <typename _Function>
7855 #if _MSC_VER >= 1800
7856         void DoCreateTask(_Function _func, const _TaskCreationCallstack & _callstack)
7857         {
7858             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts, &_M_results, _callstack);
7859         }
7860 #else
7861         void DoCreateTask(_Function _func)
7862         {
7863             _M_task = _Attributes::_Generate_Task(_func, this, _M_cts, &_M_results);
7864         }
7865 #endif
7866     protected:
7867         task<void> _M_results;
7868     };
7869 
7870     template<typename _Attributes>
7871     class _AsyncTaskThunk : public _AsyncTaskReturn<_Attributes, typename _Attributes::_ReturnType_abi, typename _Attributes::_ReturnType>
7872     {
7873     public:
7874 
7875         _AsyncTaskThunk(const _TaskType& _Task) :
7876             _AsyncTaskThunkBase(_Task)
7877         {
7878         }
7879 
7880         _AsyncTaskThunk()
7881         {
7882         }
7883 
7884     protected:
7885 
7886         virtual void _OnClose() override
7887         {
7888         }
7889 
7890         virtual void _OnCancel() override
7891         {
7892             _M_cts.cancel();
7893         }
7894     };
7895 
7896     // ***************************************************************************
7897     // Async Creation Layer:
7898     //
7899     template<typename _Function>
7900     class _AsyncTaskGeneratorThunk : public _AsyncTaskThunk<typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes>
7901     {
7902     public:
7903 
7904         typedef typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes _Attributes;
7905         typedef typename _AsyncTaskThunk<_Attributes> _Base;
7906         typedef typename _Attributes::_AsyncBaseType _AsyncBaseType;
7907 
7908 #if _MSC_VER >= 1800
7909         _AsyncTaskGeneratorThunk(const _Function& _Func, const _TaskCreationCallstack &_callstack) : _M_func(_Func), _M_creationCallstack(_callstack)
7910 #else
7911         _AsyncTaskGeneratorThunk(const _Function& _Func) : _M_func(_Func)
7912 #endif
7913         {
7914             // Virtual call here is safe as the class is declared 'sealed'
7915             _Start();
7916         }
7917 
7918     protected:
7919 
7920         //
7921         // The only thing we must do different from the base class is we must spin the hot task on transition from Created->Started. Otherwise,
7922         // let the base thunk handle everything.
7923         //
7924 
7925         virtual void _OnStart() override
7926         {
7927             //
7928             // Call the appropriate task generator to actually produce a task of the expected type. This might adapt the user lambda for progress reports,
7929             // wrap the return result in a task, or allow for direct return of a task depending on the form of the lambda.
7930             //
7931 #if _MSC_VER >= 1800
7932             DoCreateTask<_Function>(_M_func, _M_creationCallstack);
7933 #else
7934             DoCreateTask<_Function>(_M_func);
7935 #endif
7936             _Base::_OnStart();
7937         }
7938 
7939         virtual void _OnCancel() override
7940         {
7941             _Base::_OnCancel();
7942         }
7943 
7944     private:
7945 #if _MSC_VER >= 1800
7946         _TaskCreationCallstack _M_creationCallstack;
7947 #endif
7948         _Function _M_func;
7949     };
7950 } // namespace details
7951 
7952 /// <summary>
7953 ///     Creates a Windows Runtime asynchronous construct based on a user supplied lambda or function object. The return type of <c>create_async</c> is
7954 ///     one of either <c>IAsyncAction^</c>, <c>IAsyncActionWithProgress&lt;TProgress&gt;^</c>, <c>IAsyncOperation&lt;TResult&gt;^</c>, or
7955 ///     <c>IAsyncOperationWithProgress&lt;TResult, TProgress&gt;^</c> based on the signature of the lambda passed to the method.
7956 /// </summary>
7957 /// <param name="_Func">
7958 ///     The lambda or function object from which to create a Windows Runtime asynchronous construct.
7959 /// </param>
7960 /// <returns>
7961 ///     An asynchronous construct represented by an IAsyncAction^, IAsyncActionWithProgress&lt;TProgress&gt;^, IAsyncOperation&lt;TResult&gt;^, or an
7962 ///     IAsyncOperationWithProgress&lt;TResult, TProgress&gt;^. The interface returned depends on the signature of the lambda passed into the function.
7963 /// </returns>
7964 /// <remarks>
7965 ///     The return type of the lambda determines whether the construct is an action or an operation.
7966 ///     <para>Lambdas that return void cause the creation of actions. Lambdas that return a result of type <c>TResult</c> cause the creation of
7967 ///     operations of TResult.</para>
7968 ///     <para>The lambda may also return a <c>task&lt;TResult&gt;</c> which encapsulates the aysnchronous work within itself or is the continuation of
7969 ///     a chain of tasks that represent the asynchronous work. In this case, the lambda itself is executed inline, since the tasks are the ones that
7970 ///     execute asynchronously, and the return type of the lambda is unwrapped to produce the asynchronous construct returned by <c>create_async</c>.
7971 ///     This implies that a lambda that returns a task&lt;void&gt; will cause the creation of actions, and a lambda that returns a task&lt;TResult&gt; will
7972 ///     cause the creation of operations of TResult.</para>
7973 ///     <para>The lambda may take either zero, one or two arguments. The valid arguments are <c>progress_reporter&lt;TProgress&gt;</c> and
7974 ///     <c>cancellation_token</c>, in that order if both are used. A lambda without arguments causes the creation of an asynchronous construct without
7975 ///     the capability for progress reporting. A lambda that takes a progress_reporter&lt;TProgress&gt; will cause <c>create_async</c> to return an asynchronous
7976 ///     construct which reports progress of type TProgress each time the <c>report</c> method of the progress_reporter object is called. A lambda that
7977 ///     takes a cancellation_token may use that token to check for cancellation, or pass it to tasks that it creates so that cancellation of the
7978 ///     asynchronous construct causes cancellation of those tasks.</para>
7979 ///     <para>If the body of the lambda or function object returns a result (and not a task&lt;TResult&gt;), the lamdba will be executed
7980 ///     asynchronously within the process MTA in the context of a task the Runtime implicitly creates for it. The <c>IAsyncInfo::Cancel</c> method will
7981 ///     cause cancellation of the implicit task.</para>
7982 ///     <para>If the body of the lambda returns a task, the lamba executes inline, and by declaring the lambda to take an argument of type
7983 ///     <c>cancellation_token</c> you can trigger cancellation of any tasks you create within the lambda by passing that token in when you create them.
7984 ///     You may also use the <c>register_callback</c> method on the token to cause the Runtime to invoke a callback when you call <c>IAsyncInfo::Cancel</c> on
7985 ///     the async operation or action produced..</para>
7986 ///     <para>This function is only available to Windows Store apps.</para>
7987 /// </remarks>
7988 /// <seealso cref="task Class"/>
7989 /// <seealso cref="progress_reporter Class"/>
7990 /// <seealso cref="cancelation_token Class"/>
7991 /**/
7992 template<typename _ReturnType, typename _Function>
7993 __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
7994 details::_AsyncTaskGeneratorThunk<_Function>* create_async(const _Function& _Func)
7995 {
7996     static_assert(std::is_same<decltype(details::_IsValidCreateAsync<_ReturnType>(_Func, 0, 0, 0, 0, 0, 0, 0, 0)), std::true_type>::value,
7997         "argument to create_async must be a callable object taking zero, one, two or three arguments");
7998 #if _MSC_VER >= 1800
7999     Microsoft::WRL::ComPtr<details::_AsyncTaskGeneratorThunk<_Function>> _AsyncInfo = Microsoft::WRL::Make<details::_AsyncTaskGeneratorThunk<_Function>>(_Func, _CAPTURE_CALLSTACK());
8000 #else
8001     Microsoft::WRL::ComPtr<details::_AsyncTaskGeneratorThunk<_Function>> _AsyncInfo = Microsoft::WRL::Make<details::_AsyncTaskGeneratorThunk<_Function>>(_Func);
8002     _AsyncInfo->_SetTaskCreationAddressHint(_ReturnAddress());
8003 #endif
8004     return _AsyncInfo.Detach();
8005 }
8006 
8007 namespace details
8008 {
8009 #if _MSC_VER < 1800
8010     // Internal API which retrieves the next async id.
8011     _CRTIMP2 unsigned int __cdecl _GetNextAsyncId();
8012 #endif
8013     // Helper struct for when_all operators to know when tasks have completed
8014     template<typename _Type>
8015     struct _RunAllParam
8016     {
8017         _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
8018         {
8019         }
8020 
8021         void _Resize(size_t _Len, bool _SkipVector = false)
8022         {
8023             _M_numTasks = _Len;
8024             if (!_SkipVector)
8025 #if _MSC_VER >= 1800
8026             {
8027                 _M_vector._Result.resize(_Len);
8028             }
8029 #else
8030                 _M_vector.resize(_Len);
8031             _M_contexts.resize(_Len);
8032 #endif
8033         }
8034 
8035         task_completion_event<_Unit_type>       _M_completed;
8036         atomic_size_t                           _M_completeCount;
8037 #if _MSC_VER >= 1800
8038         _ResultHolder<std::vector<_Type> >      _M_vector;
8039         _ResultHolder<_Type>                    _M_mergeVal;
8040 #else
8041         std::vector<_Type>                      _M_vector;
8042         std::vector<_ContextCallback>           _M_contexts;
8043         _Type                                   _M_mergeVal;
8044 #endif
8045         size_t                                  _M_numTasks;
8046     };
8047 
8048 #if _MSC_VER >= 1800
8049     template<typename _Type>
8050     struct _RunAllParam<std::vector<_Type> >
8051     {
8052         _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
8053         {
8054         }
8055 
8056         void _Resize(size_t _Len, bool _SkipVector = false)
8057         {
8058             _M_numTasks = _Len;
8059 
8060             if (!_SkipVector)
8061             {
8062                 _M_vector.resize(_Len);
8063             }
8064         }
8065 
8066         task_completion_event<_Unit_type>       _M_completed;
8067         std::vector<_ResultHolder<std::vector<_Type> > >  _M_vector;
8068         atomic_size_t     _M_completeCount;
8069         size_t                                  _M_numTasks;
8070     };
8071 #endif
8072 
8073     // Helper struct specialization for void
8074     template<>
8075 #if _MSC_VER >= 1800
8076     struct _RunAllParam<_Unit_type>
8077 #else
8078     struct _RunAllParam<void>
8079 #endif
8080     {
8081         _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
8082         {
8083         }
8084 
8085         void _Resize(size_t _Len)
8086         {
8087             _M_numTasks = _Len;
8088         }
8089 
8090         task_completion_event<_Unit_type> _M_completed;
8091         atomic_size_t _M_completeCount;
8092         size_t _M_numTasks;
8093     };
8094 
8095     inline void _JoinAllTokens_Add(const Concurrency::cancellation_token_source& _MergedSrc, Concurrency::details::_CancellationTokenState *_PJoinedTokenState)
8096     {
8097         if (_PJoinedTokenState != nullptr && _PJoinedTokenState != Concurrency::details::_CancellationTokenState::_None())
8098         {
8099             Concurrency::cancellation_token _T = Concurrency::cancellation_token::_FromImpl(_PJoinedTokenState);
8100             _T.register_callback([=](){
8101                 _MergedSrc.cancel();
8102             });
8103         }
8104     }
8105 
8106     template<typename _ElementType, typename _Function, typename _TaskType>
8107     void _WhenAllContinuationWrapper(_RunAllParam<_ElementType>* _PParam, _Function _Func, task<_TaskType>& _Task)
8108     {
8109         if (_Task._GetImpl()->_IsCompleted())
8110         {
8111             _Func();
8112 #if _MSC_VER >= 1800
8113             if (Concurrency::details::atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
8114 #else
8115             if (_InterlockedIncrementSizeT(&_PParam->_M_completeCount) == _PParam->_M_numTasks)
8116 #endif
8117             {
8118                 // Inline execute its direct continuation, the _ReturnTask
8119                 _PParam->_M_completed.set(_Unit_type());
8120                 // It's safe to delete it since all usage of _PParam in _ReturnTask has been finished.
8121                 delete _PParam;
8122             }
8123         }
8124         else
8125         {
8126             _CONCRT_ASSERT(_Task._GetImpl()->_IsCanceled());
8127             if (_Task._GetImpl()->_HasUserException())
8128             {
8129                 // _Cancel will return false if the TCE is already canceled with or without exception
8130                 _PParam->_M_completed._Cancel(_Task._GetImpl()->_GetExceptionHolder());
8131             }
8132             else
8133             {
8134                 _PParam->_M_completed._Cancel();
8135             }
8136 #if _MSC_VER >= 1800
8137             if (Concurrency::details::atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
8138 #else
8139             if (_InterlockedIncrementSizeT(&_PParam->_M_completeCount) == _PParam->_M_numTasks)
8140 #endif
8141             {
8142                 delete _PParam;
8143             }
8144         }
8145     }
8146 
8147     template<typename _ElementType, typename _Iterator>
8148     struct _WhenAllImpl
8149     {
8150 #if _MSC_VER >= 1800
8151         static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
8152 #else
8153         static task<std::vector<_ElementType>> _Perform(Concurrency::details::_CancellationTokenState *_PTokenState, _Iterator _Begin, _Iterator _End)
8154 #endif
8155         {
8156 #if _MSC_VER >= 1800
8157             Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
8158 #endif
8159             auto _PParam = new _RunAllParam<_ElementType>();
8160             Concurrency::cancellation_token_source _MergedSource;
8161 
8162             // Step1: Create task completion event.
8163 #if _MSC_VER >= 1800
8164             task_options _Options(_TaskOptions);
8165             _Options.set_cancellation_token(_MergedSource.get_token());
8166             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
8167 #else
8168             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
8169 #endif
8170             // The return task must be created before step 3 to enforce inline execution.
8171             auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type, std::vector<_ElementType>* retVal) -> HRESULT {
8172 #if _MSC_VER >= 1800
8173                 * retVal = _PParam->_M_vector.Get();
8174 #else
8175                 auto _Result = _PParam->_M_vector; // copy by value
8176 
8177                 size_t _Index = 0;
8178                 for (auto _It = _Result.begin(); _It != _Result.end(); ++_It)
8179                 {
8180                     *_It = _ResultContext<_ElementType>::_GetValue(*_It, _PParam->_M_contexts[_Index++], false);
8181                 }
8182                 *retVal = _Result;
8183 #endif
8184                 return S_OK;
8185 #if _MSC_VER >= 1800
8186             }, nullptr);
8187 #else
8188             }, nullptr, true);
8189 #endif
8190             // Step2: Combine and check tokens, and count elements in range.
8191             if (_PTokenState)
8192             {
8193                 details::_JoinAllTokens_Add(_MergedSource, _PTokenState);
8194                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
8195             }
8196             else
8197             {
8198                 size_t _TaskNum = 0;
8199                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8200                 {
8201                     _TaskNum++;
8202                     details::_JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
8203                 }
8204                 _PParam->_Resize(_TaskNum);
8205             }
8206 
8207             // Step3: Check states of previous tasks.
8208             if (_Begin == _End)
8209             {
8210                 _PParam->_M_completed.set(_Unit_type());
8211                 delete _PParam;
8212             }
8213             else
8214             {
8215                 size_t _Index = 0;
8216                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8217                 {
8218                     if (_PTask->is_apartment_aware())
8219                     {
8220                         _ReturnTask._SetAsync();
8221                     }
8222 
8223                     _PTask->_Then([_PParam, _Index](task<_ElementType> _ResultTask) -> HRESULT {
8224 
8225 #if _MSC_VER >= 1800
8226                         //  Dev10 compiler bug
8227                         typedef _ElementType _ElementTypeDev10;
8228                         auto _PParamCopy = _PParam;
8229                         auto _IndexCopy = _Index;
8230                         auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask](){
8231                             _PParamCopy->_M_vector._Result[_IndexCopy] = _ResultTask._GetImpl()->_GetResult();
8232                         };
8233 #else
8234                         auto _Func = [_PParam, _Index, &_ResultTask](){
8235                             _PParam->_M_vector[_Index] = _ResultTask._GetImpl()->_GetResult();
8236                             _PParam->_M_contexts[_Index] = _ResultContext<_ElementType>::_GetContext(false);
8237                         };
8238 #endif
8239                         _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
8240                         return S_OK;
8241 #if _MSC_VER >= 1800
8242                     }, Concurrency::details::_CancellationTokenState::_None());
8243 #else
8244                     }, Concurrency::details::_CancellationTokenState::_None(), false);
8245 #endif
8246 
8247                     _Index++;
8248                 }
8249             }
8250 
8251             return _ReturnTask;
8252         }
8253     };
8254 
8255     template<typename _ElementType, typename _Iterator>
8256     struct _WhenAllImpl<std::vector<_ElementType>, _Iterator>
8257     {
8258 #if _MSC_VER >= 1800
8259         static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
8260 #else
8261         static task<std::vector<_ElementType>> _Perform(Concurrency::details::_CancellationTokenState *_PTokenState, _Iterator _Begin, _Iterator _End)
8262 #endif
8263         {
8264 #if _MSC_VER >= 1800
8265             Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
8266 #endif
8267             auto _PParam = new _RunAllParam<std::vector<_ElementType>>();
8268             Concurrency::cancellation_token_source _MergedSource;
8269 
8270             // Step1: Create task completion event.
8271 #if _MSC_VER >= 1800
8272             task_options _Options(_TaskOptions);
8273             _Options.set_cancellation_token(_MergedSource.get_token());
8274             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
8275 #else
8276             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
8277 #endif
8278             // The return task must be created before step 3 to enforce inline execution.
8279             auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type, std::vector<_ElementType>* retVal) -> HRESULT {
8280                 _CONCRT_ASSERT(_PParam->_M_completeCount == _PParam->_M_numTasks);
8281                 std::vector<_ElementType> _Result;
8282                 for (size_t _I = 0; _I < _PParam->_M_numTasks; _I++)
8283                 {
8284 #if _MSC_VER >= 1800
8285                     const std::vector<_ElementType>& _Vec = _PParam->_M_vector[_I].Get();
8286 #else
8287                     std::vector<_ElementType>& _Vec = _PParam->_M_vector[_I];
8288 
8289                     for (auto _It = _Vec.begin(); _It != _Vec.end(); ++_It)
8290                     {
8291                         *_It = _ResultContext<_ElementType>::_GetValue(*_It, _PParam->_M_contexts[_I], false);
8292                     }
8293 #endif
8294                     _Result.insert(_Result.end(), _Vec.begin(), _Vec.end());
8295                 }
8296                 *retVal = _Result;
8297                 return S_OK;
8298 #if _MSC_VER >= 1800
8299             }, nullptr);
8300 #else
8301             }, nullptr, true);
8302 #endif
8303 
8304             // Step2: Combine and check tokens, and count elements in range.
8305             if (_PTokenState)
8306             {
8307                 details::_JoinAllTokens_Add(_MergedSource, _PTokenState);
8308                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
8309             }
8310             else
8311             {
8312                 size_t _TaskNum = 0;
8313                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8314                 {
8315                     _TaskNum++;
8316                     details::_JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
8317                 }
8318                 _PParam->_Resize(_TaskNum);
8319             }
8320 
8321             // Step3: Check states of previous tasks.
8322             if (_Begin == _End)
8323             {
8324                 _PParam->_M_completed.set(_Unit_type());
8325                 delete _PParam;
8326             }
8327             else
8328             {
8329                 size_t _Index = 0;
8330                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8331                 {
8332                     if (_PTask->is_apartment_aware())
8333                     {
8334                         _ReturnTask._SetAsync();
8335                     }
8336 
8337                     _PTask->_Then([_PParam, _Index](task<std::vector<_ElementType>> _ResultTask) -> HRESULT {
8338 #if _MSC_VER >= 1800
8339                         //  Dev10 compiler bug
8340                         typedef _ElementType _ElementTypeDev10;
8341                         auto _PParamCopy = _PParam;
8342                         auto _IndexCopy = _Index;
8343                         auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask]() {
8344                             _PParamCopy->_M_vector[_IndexCopy].Set(_ResultTask._GetImpl()->_GetResult());
8345                         };
8346 #else
8347                         auto _Func = [_PParam, _Index, &_ResultTask]() {
8348                             _PParam->_M_vector[_Index] = _ResultTask._GetImpl()->_GetResult();
8349                             _PParam->_M_contexts[_Index] = _ResultContext<_ElementType>::_GetContext(false);
8350                         };
8351 #endif
8352                         _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
8353                         return S_OK;
8354 #if _MSC_VER >= 1800
8355                     }, Concurrency::details::_CancellationTokenState::_None());
8356 #else
8357                     }, Concurrency::details::_CancellationTokenState::_None(), false);
8358 #endif
8359 
8360                     _Index++;
8361                 }
8362             }
8363 
8364             return  _ReturnTask;
8365         }
8366     };
8367 
8368     template<typename _Iterator>
8369     struct _WhenAllImpl<void, _Iterator>
8370     {
8371 #if _MSC_VER >= 1800
8372         static task<void> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
8373 #else
8374         static task<void> _Perform(Concurrency::details::_CancellationTokenState *_PTokenState, _Iterator _Begin, _Iterator _End)
8375 #endif
8376         {
8377 #if _MSC_VER >= 1800
8378             Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
8379 #endif
8380             auto _PParam = new _RunAllParam<_Unit_type>();
8381             Concurrency::cancellation_token_source _MergedSource;
8382 
8383             // Step1: Create task completion event.
8384 #if _MSC_VER >= 1800
8385             task_options _Options(_TaskOptions);
8386             _Options.set_cancellation_token(_MergedSource.get_token());
8387             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
8388 #else
8389             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
8390 #endif
8391             // The return task must be created before step 3 to enforce inline execution.
8392             auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> HRESULT { return S_OK;
8393 #if _MSC_VER >= 1800
8394             }, nullptr);
8395 #else
8396             }, nullptr, false);
8397 #endif
8398 
8399             // Step2: Combine and check tokens, and count elements in range.
8400             if (_PTokenState)
8401             {
8402                 details::_JoinAllTokens_Add(_MergedSource, _PTokenState);
8403                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
8404             }
8405             else
8406             {
8407                 size_t _TaskNum = 0;
8408                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8409                 {
8410                     _TaskNum++;
8411                     details::_JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
8412                 }
8413                 _PParam->_Resize(_TaskNum);
8414             }
8415 
8416             // Step3: Check states of previous tasks.
8417             if (_Begin == _End)
8418             {
8419                 _PParam->_M_completed.set(_Unit_type());
8420                 delete _PParam;
8421             }
8422             else
8423             {
8424                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8425                 {
8426                     if (_PTask->is_apartment_aware())
8427                     {
8428                         _ReturnTask._SetAsync();
8429                     }
8430 
8431                     _PTask->_Then([_PParam](task<void> _ResultTask) -> HRESULT {
8432 
8433                         auto _Func = []() -> HRESULT { return S_OK;  };
8434                         _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
8435                         return S_OK;
8436 #if _MSC_VER >= 1800
8437                     }, Concurrency::details::_CancellationTokenState::_None());
8438 #else
8439                     }, Concurrency::details::_CancellationTokenState::_None(), false);
8440 #endif
8441                 }
8442             }
8443 
8444             return _ReturnTask;
8445         }
8446     };
8447 
8448     template<typename _ReturnType>
8449     task<std::vector<_ReturnType>> _WhenAllVectorAndValue(const task<std::vector<_ReturnType>>& _VectorTask, const task<_ReturnType>& _ValueTask,
8450         bool _OutputVectorFirst)
8451     {
8452         auto _PParam = new _RunAllParam<_ReturnType>();
8453         Concurrency::cancellation_token_source _MergedSource;
8454 
8455         // Step1: Create task completion event.
8456         task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
8457         // The return task must be created before step 3 to enforce inline execution.
8458         auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type, std::vector<_ReturnType>* retVal) -> HRESULT {
8459             _CONCRT_ASSERT(_PParam->_M_completeCount == 2);
8460 #if _MSC_VER >= 1800
8461             auto _Result = _PParam->_M_vector.Get(); // copy by value
8462             auto _mergeVal = _PParam->_M_mergeVal.Get();
8463 #else
8464             auto _Result = _PParam->_M_vector; // copy by value
8465             for (auto _It = _Result.begin(); _It != _Result.end(); ++_It)
8466             {
8467                 *_It = _ResultContext<_ReturnType>::_GetValue(*_It, _PParam->_M_contexts[0], false);
8468             }
8469 #endif
8470 
8471             if (_OutputVectorFirst == true)
8472             {
8473 #if _MSC_VER >= 1800
8474                 _Result.push_back(_mergeVal);
8475 #else
8476                 _Result.push_back(_ResultContext<_ReturnType>::_GetValue(_PParam->_M_mergeVal, _PParam->_M_contexts[1], false));
8477 #endif
8478             }
8479             else
8480             {
8481 #if _MSC_VER >= 1800
8482                 _Result.insert(_Result.begin(), _mergeVal);
8483 #else
8484                 _Result.insert(_Result.begin(), _ResultContext<_ReturnType>::_GetValue(_PParam->_M_mergeVal, _PParam->_M_contexts[1], false));
8485 #endif
8486             }
8487             *retVal = _Result;
8488             return S_OK;
8489         }, nullptr, true);
8490 
8491         // Step2: Combine and check tokens.
8492         _JoinAllTokens_Add(_MergedSource, _VectorTask._GetImpl()->_M_pTokenState);
8493         _JoinAllTokens_Add(_MergedSource, _ValueTask._GetImpl()->_M_pTokenState);
8494 
8495         // Step3: Check states of previous tasks.
8496         _PParam->_Resize(2, true);
8497 
8498         if (_VectorTask.is_apartment_aware() || _ValueTask.is_apartment_aware())
8499         {
8500             _ReturnTask._SetAsync();
8501         }
8502         _VectorTask._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) -> HRESULT {
8503 #if _MSC_VER >= 1800
8504             //  Dev10 compiler bug
8505             typedef _ReturnType _ReturnTypeDev10;
8506             auto _PParamCopy = _PParam;
8507             auto _Func = [_PParamCopy, &_ResultTask]() {
8508                 auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
8509                 _PParamCopy->_M_vector.Set(_ResultLocal);
8510             };
8511 #else
8512             auto _Func = [_PParam, &_ResultTask]() {
8513                 _PParam->_M_vector = _ResultTask._GetImpl()->_GetResult();
8514                 _PParam->_M_contexts[0] = _ResultContext<_ReturnType>::_GetContext(false);
8515             };
8516 #endif
8517 
8518             _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
8519             return S_OK;
8520 #if _MSC_VER >= 1800
8521         }, _CancellationTokenState::_None());
8522 #else
8523         }, _CancellationTokenState::_None(), false);
8524 #endif
8525         _ValueTask._Then([_PParam](task<_ReturnType> _ResultTask) -> HRESULT {
8526 #if _MSC_VER >= 1800
8527             //  Dev10 compiler bug
8528             typedef _ReturnType _ReturnTypeDev10;
8529             auto _PParamCopy = _PParam;
8530             auto _Func = [_PParamCopy, &_ResultTask]() {
8531                 auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
8532                 _PParamCopy->_M_mergeVal.Set(_ResultLocal);
8533             };
8534 #else
8535             auto _Func = [_PParam, &_ResultTask]() {
8536                 _PParam->_M_mergeVal = _ResultTask._GetImpl()->_GetResult();
8537                 _PParam->_M_contexts[1] = _ResultContext<_ReturnType>::_GetContext(false);
8538             };
8539 #endif
8540             _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
8541             return S_OK;
8542 #if _MSC_VER >= 1800
8543         }, _CancellationTokenState::_None());
8544 #else
8545         }, _CancellationTokenState::_None(), false);
8546 #endif
8547 
8548         return _ReturnTask;
8549     }
8550 } // namespace details
8551 
8552 #if _MSC_VER < 1800
8553 /// <summary>
8554 ///     Creates a task that will complete successfully when all of the tasks supplied as arguments complete successfully.
8555 /// </summary>
8556 /// <typeparam name="_Iterator">
8557 ///     The type of the input iterator.
8558 /// </typeparam>
8559 /// <param name="_Begin">
8560 ///     The position of the first element in the range of elements to be combined into the resulting task.
8561 /// </param>
8562 /// <param name="_End">
8563 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
8564 /// </param>
8565 /// <returns>
8566 ///     A task that completes sucessfully when all of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8567 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8568 ///     task will also be a <c>task&lt;void&gt;</c>.
8569 /// </returns>
8570 /// <remarks>
8571 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8572 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8573 /// </remarks>
8574 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8575 /**/
8576 template <typename _Iterator>
8577 auto when_all(_Iterator _Begin, _Iterator _End)
8578 -> decltype (details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(nullptr, _Begin, _End))
8579 {
8580     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
8581     return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(nullptr, _Begin, _End);
8582 }
8583 #endif
8584 
8585 /// <summary>
8586 ///     Creates a task that will complete successfully when all of the tasks supplied as arguments complete successfully.
8587 /// </summary>
8588 /// <typeparam name="_Iterator">
8589 ///     The type of the input iterator.
8590 /// </typeparam>
8591 /// <param name="_Begin">
8592 ///     The position of the first element in the range of elements to be combined into the resulting task.
8593 /// </param>
8594 /// <param name="_End">
8595 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
8596 /// </param>
8597 /// <param name="_CancellationToken">
8598 ///     The cancellation token which controls cancellation of the returned task. If you do not provide a cancellation token, the resulting
8599 ///     task will be created with a token that is a combination of all the cancelable tokens (tokens created by methods other than
8600 ///     <c>cancellation_token::none()</c>of the tasks supplied.
8601 /// </param>
8602 /// <returns>
8603 ///     A task that completes sucessfully when all of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8604 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8605 ///     task will also be a <c>task&lt;void&gt;</c>.
8606 /// </returns>
8607 /// <remarks>
8608 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8609 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8610 /// </remarks>
8611 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8612 /**/
8613 template <typename _Iterator>
8614 #if _MSC_VER >= 1800
8615 auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
8616 -> decltype (details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
8617 {
8618     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
8619     return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
8620 }
8621 #else
8622 auto when_all(_Iterator _Begin, _Iterator _End, Concurrency::cancellation_token _CancellationToken)
8623 -> decltype (details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End))
8624 {
8625     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
8626     return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End);
8627 }
8628 #endif
8629 
8630 /// <summary>
8631 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully.
8632 /// </summary>
8633 /// <typeparam name="_ReturnType">
8634 ///     The type of the returned task.
8635 /// </typeparam>
8636 /// <param name="_Lhs">
8637 ///     The first task to combine into the resulting task.
8638 /// </param>
8639 /// <param name="_Rhs">
8640 ///     The second task to combine into the resulting task.
8641 /// </param>
8642 /// <returns>
8643 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8644 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8645 ///     task will also be a <c>task&lt;void&gt;</c>.
8646 ///     <para> To allow for a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp; operator
8647 ///     produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
8648 /// </returns>
8649 /// <remarks>
8650 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8651 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8652 /// </remarks>
8653 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8654 /**/
8655 template<typename _ReturnType>
8656 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
8657 {
8658     task<_ReturnType> _PTasks[2] = { _Lhs, _Rhs };
8659     return when_all(_PTasks, _PTasks + 2);
8660 }
8661 
8662 /// <summary>
8663 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully.
8664 /// </summary>
8665 /// <typeparam name="_ReturnType">
8666 ///     The type of the returned task.
8667 /// </typeparam>
8668 /// <param name="_Lhs">
8669 ///     The first task to combine into the resulting task.
8670 /// </param>
8671 /// <param name="_Rhs">
8672 ///     The second task to combine into the resulting task.
8673 /// </param>
8674 /// <returns>
8675 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8676 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8677 ///     task will also be a <c>task&lt;void&gt;</c>.
8678 ///     <para> To allow for a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp; operator
8679 ///     produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
8680 /// </returns>
8681 /// <remarks>
8682 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8683 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8684 /// </remarks>
8685 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8686 /**/
8687 template<typename _ReturnType>
8688 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
8689 {
8690     return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true);
8691 }
8692 
8693 /// <summary>
8694 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully.
8695 /// </summary>
8696 /// <typeparam name="_ReturnType">
8697 ///     The type of the returned task.
8698 /// </typeparam>
8699 /// <param name="_Lhs">
8700 ///     The first task to combine into the resulting task.
8701 /// </param>
8702 /// <param name="_Rhs">
8703 ///     The second task to combine into the resulting task.
8704 /// </param>
8705 /// <returns>
8706 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8707 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8708 ///     task will also be a <c>task&lt;void&gt;</c>.
8709 ///     <para> To allow for a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp; operator
8710 ///     produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
8711 /// </returns>
8712 /// <remarks>
8713 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8714 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8715 /// </remarks>
8716 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8717 /**/
8718 template<typename _ReturnType>
8719 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
8720 {
8721     return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false);
8722 }
8723 
8724 /// <summary>
8725 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully.
8726 /// </summary>
8727 /// <typeparam name="_ReturnType">
8728 ///     The type of the returned task.
8729 /// </typeparam>
8730 /// <param name="_Lhs">
8731 ///     The first task to combine into the resulting task.
8732 /// </param>
8733 /// <param name="_Rhs">
8734 ///     The second task to combine into the resulting task.
8735 /// </param>
8736 /// <returns>
8737 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8738 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8739 ///     task will also be a <c>task&lt;void&gt;</c>.
8740 ///     <para> To allow for a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp; operator
8741 ///     produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
8742 /// </returns>
8743 /// <remarks>
8744 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8745 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8746 /// </remarks>
8747 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8748 /**/
8749 template<typename _ReturnType>
8750 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
8751 {
8752     task<std::vector<_ReturnType>> _PTasks[2] = { _Lhs, _Rhs };
8753     return when_all(_PTasks, _PTasks + 2);
8754 }
8755 
8756 /// <summary>
8757 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete successfully.
8758 /// </summary>
8759 /// <typeparam name="_ReturnType">
8760 ///     The type of the returned task.
8761 /// </typeparam>
8762 /// <param name="_Lhs">
8763 ///     The first task to combine into the resulting task.
8764 /// </param>
8765 /// <param name="_Rhs">
8766 ///     The second task to combine into the resulting task.
8767 /// </param>
8768 /// <returns>
8769 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type <c>T</c>,
8770 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the input tasks are of type <c>void</c> the output
8771 ///     task will also be a <c>task&lt;void&gt;</c>.
8772 ///     <para> To allow for a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp; operator
8773 ///     produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
8774 /// </returns>
8775 /// <remarks>
8776 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception,
8777 ///     if one is encoutered, will be thrown if you call <c>get()</c> or <c>wait()</c> on that task.
8778 /// </remarks>
8779 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
8780 /**/
8781 inline task<void> operator&&(const task<void> & _Lhs, const task<void> & _Rhs)
8782 {
8783     task<void> _PTasks[2] = { _Lhs, _Rhs };
8784     return when_all(_PTasks, _PTasks + 2);
8785 }
8786 
8787 namespace details
8788 {
8789     // Helper struct for when_any operators to know when tasks have completed
8790     template <typename _CompletionType>
8791     struct _RunAnyParam
8792     {
8793         _RunAnyParam() : _M_completeCount(0), _M_numTasks(0), _M_exceptionRelatedToken(nullptr), _M_fHasExplicitToken(false)
8794         {
8795         }
8796         ~_RunAnyParam()
8797         {
8798             if (Concurrency::details::_CancellationTokenState::_IsValid(_M_exceptionRelatedToken))
8799                 _M_exceptionRelatedToken->_Release();
8800         }
8801         task_completion_event<_CompletionType>      _M_Completed;
8802         Concurrency::cancellation_token_source                   _M_cancellationSource;
8803         Concurrency::details::_CancellationTokenState*            _M_exceptionRelatedToken;
8804         atomic_size_t         _M_completeCount;
8805         size_t                                      _M_numTasks;
8806         bool                                        _M_fHasExplicitToken;
8807     };
8808 
8809     template<typename _CompletionType, typename _Function, typename _TaskType>
8810     void _WhenAnyContinuationWrapper(_RunAnyParam<_CompletionType> * _PParam, const _Function & _Func, task<_TaskType>& _Task)
8811     {
8812         bool _IsTokenCancled = !_PParam->_M_fHasExplicitToken && _Task._GetImpl()->_M_pTokenState != Concurrency::details::_CancellationTokenState::_None() && _Task._GetImpl()->_M_pTokenState->_IsCanceled();
8813         if (_Task._GetImpl()->_IsCompleted() && !_IsTokenCancled)
8814         {
8815             _Func();
8816 #if _MSC_VER >= 1800
8817             if (Concurrency::details::atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
8818 #else
8819             if (_InterlockedIncrementSizeT(&_PParam->_M_completeCount) == _PParam->_M_numTasks)
8820 #endif
8821             {
8822                 delete _PParam;
8823             }
8824         }
8825         else
8826         {
8827             _CONCRT_ASSERT(_Task._GetImpl()->_IsCanceled() || _IsTokenCancled);
8828             if (_Task._GetImpl()->_HasUserException() && !_IsTokenCancled)
8829             {
8830                 if (_PParam->_M_Completed._StoreException(_Task._GetImpl()->_GetExceptionHolder()))
8831                 {
8832                     // This can only enter once.
8833                     _PParam->_M_exceptionRelatedToken = _Task._GetImpl()->_M_pTokenState;
8834                     _CONCRT_ASSERT(_PParam->_M_exceptionRelatedToken);
8835                     // Deref token will be done in the _PParam destructor.
8836                     if (_PParam->_M_exceptionRelatedToken != Concurrency::details::_CancellationTokenState::_None())
8837                     {
8838                         _PParam->_M_exceptionRelatedToken->_Reference();
8839                     }
8840                 }
8841             }
8842 
8843 #if _MSC_VER >= 1800
8844             if (Concurrency::details::atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
8845 #else
8846             if (_InterlockedIncrementSizeT(&_PParam->_M_completeCount) == _PParam->_M_numTasks)
8847 #endif
8848             {
8849                 // If no one has be completed so far, we need to make some final cancellation decision.
8850                 if (!_PParam->_M_Completed._IsTriggered())
8851                 {
8852                     // If we already explicit token, we can skip the token join part.
8853                     if (!_PParam->_M_fHasExplicitToken)
8854                     {
8855                         if (_PParam->_M_exceptionRelatedToken)
8856                         {
8857                             details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _PParam->_M_exceptionRelatedToken);
8858                         }
8859                         else
8860                         {
8861                             // If haven't captured any exception token yet, there was no exception for all those tasks,
8862                             // so just pick a random token (current one) for normal cancellation.
8863                             details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Task._GetImpl()->_M_pTokenState);
8864                         }
8865                     }
8866                     // Do exception cancellation or normal cancellation based on whether it has stored exception.
8867                     _PParam->_M_Completed._Cancel();
8868                 }
8869                 delete _PParam;
8870             }
8871         }
8872     }
8873 
8874     template<typename _ElementType, typename _Iterator>
8875     struct _WhenAnyImpl
8876     {
8877 #if _MSC_VER >= 1800
8878         static task<std::pair<_ElementType, size_t>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
8879 #else
8880         static task<std::pair<_ElementType, size_t>> _Perform(Concurrency::details::_CancellationTokenState *_PTokenState, _Iterator _Begin, _Iterator _End)
8881 #endif
8882         {
8883             if (_Begin == _End)
8884             {
8885                 throw Concurrency::invalid_operation("when_any(begin, end) cannot be called on an empty container.");
8886             }
8887 #if _MSC_VER >= 1800
8888             Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
8889 #endif
8890             auto _PParam = new _RunAnyParam<std::pair<std::pair<_ElementType, size_t>, Concurrency::details::_CancellationTokenState *>>();
8891 
8892             if (_PTokenState)
8893             {
8894                 details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
8895                 _PParam->_M_fHasExplicitToken = true;
8896             }
8897 #if _MSC_VER >= 1800
8898             task_options _Options(_TaskOptions);
8899             _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
8900             task<std::pair<std::pair<_ElementType, size_t>, Concurrency::details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
8901 #else
8902             task<std::pair<std::pair<_ElementType, size_t>, Concurrency::details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
8903             _Any_tasks_completed._GetImpl()->_M_fRuntimeAggregate = true;
8904 #endif
8905             // Keep a copy ref to the token source
8906             auto _CancellationSource = _PParam->_M_cancellationSource;
8907 
8908             _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
8909             size_t index = 0;
8910             for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8911             {
8912                 if (_PTask->is_apartment_aware())
8913                 {
8914                     _Any_tasks_completed._SetAsync();
8915                 }
8916 
8917                 _PTask->_Then([_PParam, index](task<_ElementType> _ResultTask) -> HRESULT {
8918 #if _MSC_VER >= 1800
8919                     auto _PParamCopy = _PParam; // Dev10
8920                     auto _IndexCopy = index; // Dev10
8921                     auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
8922                         _PParamCopy->_M_Completed.set(std::make_pair(std::make_pair(_ResultTask._GetImpl()->_GetResult(), _IndexCopy), _ResultTask._GetImpl()->_M_pTokenState));
8923                     };
8924 #else
8925                     auto _Func = [&_ResultTask, _PParam, index]() {
8926                         _PParam->_M_Completed.set(std::make_pair(std::make_pair(_ResultTask._GetImpl()->_GetResult(), index), _ResultTask._GetImpl()->_M_pTokenState));
8927                     };
8928 #endif
8929                     _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
8930                     return S_OK;
8931 #if _MSC_VER >= 1800
8932                 }, Concurrency::details::_CancellationTokenState::_None());
8933 #else
8934                 }, Concurrency::details::_CancellationTokenState::_None(), false);
8935 #endif
8936                 index++;
8937             }
8938 
8939             // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
8940             return _Any_tasks_completed._Then([=](std::pair<std::pair<_ElementType, size_t>, Concurrency::details::_CancellationTokenState *> _Result, std::pair<_ElementType, size_t>* retVal) -> HRESULT {
8941                 _CONCRT_ASSERT(_Result.second);
8942                 if (!_PTokenState)
8943                 {
8944                     details::_JoinAllTokens_Add(_CancellationSource, _Result.second);
8945                 }
8946                 *retVal = _Result.first;
8947                 return S_OK;
8948 #if _MSC_VER >= 1800
8949             }, nullptr);
8950 #else
8951             }, nullptr, true);
8952 #endif
8953         }
8954     };
8955 
8956     template<typename _Iterator>
8957     struct _WhenAnyImpl<void, _Iterator>
8958     {
8959 #if _MSC_VER >= 1800
8960         static task<size_t> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
8961 #else
8962         static task<size_t> _Perform(Concurrency::details::_CancellationTokenState *_PTokenState, _Iterator _Begin, _Iterator _End)
8963 #endif
8964         {
8965             if (_Begin == _End)
8966             {
8967                 throw Concurrency::invalid_operation("when_any(begin, end) cannot be called on an empty container.");
8968             }
8969 #if _MSC_VER >= 1800
8970             Concurrency::details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
8971 #endif
8972             auto _PParam = new _RunAnyParam<std::pair<size_t, Concurrency::details::_CancellationTokenState *>>();
8973 
8974             if (_PTokenState)
8975             {
8976                 details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
8977                 _PParam->_M_fHasExplicitToken = true;
8978             }
8979 
8980 #if _MSC_VER >= 1800
8981             task_options _Options(_TaskOptions);
8982             _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
8983             task<std::pair<size_t, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
8984 #else
8985             task<std::pair<size_t, Concurrency::details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
8986 #endif
8987             // Keep a copy ref to the token source
8988             auto _CancellationSource = _PParam->_M_cancellationSource;
8989 
8990             _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
8991             size_t index = 0;
8992             for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
8993             {
8994                 if (_PTask->is_apartment_aware())
8995                 {
8996                     _Any_tasks_completed._SetAsync();
8997                 }
8998 
8999                 _PTask->_Then([_PParam, index](task<void> _ResultTask) -> HRESULT {
9000 #if _MSC_VER >= 1800
9001                     auto _PParamCopy = _PParam; // Dev10
9002                     auto _IndexCopy = index; // Dev10
9003                     auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
9004                         _PParamCopy->_M_Completed.set(std::make_pair(_IndexCopy, _ResultTask._GetImpl()->_M_pTokenState));
9005                     };
9006 #else
9007                     auto _Func = [&_ResultTask, _PParam, index]() {
9008                         _PParam->_M_Completed.set(std::make_pair(index, _ResultTask._GetImpl()->_M_pTokenState));
9009                     };
9010 #endif
9011                     _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
9012                     return S_OK;
9013 #if _MSC_VER >= 1800
9014                 }, Concurrency::details::_CancellationTokenState::_None());
9015 #else
9016                 }, Concurrency::details::_CancellationTokenState::_None(), false);
9017 #endif
9018 
9019                 index++;
9020             }
9021 
9022             // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
9023             return _Any_tasks_completed._Then([=](std::pair<size_t, Concurrency::details::_CancellationTokenState *> _Result, size_t* retVal) -> HRESULT {
9024                 _CONCRT_ASSERT(_Result.second);
9025                 if (!_PTokenState)
9026                 {
9027                     details::_JoinAllTokens_Add(_CancellationSource, _Result.second);
9028                 }
9029                 *retVal = _Result.first;
9030                 return S_OK;
9031 #if _MSC_VER >= 1800
9032             }, nullptr);
9033 #else
9034             }, nullptr, false);
9035 #endif
9036         }
9037     };
9038 } // namespace details
9039 
9040 /// <summary>
9041 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes successfully.
9042 /// </summary>
9043 /// <typeparam name="_Iterator">
9044 ///     The type of the input iterator.
9045 /// </typeparam>
9046 /// <param name="_Begin">
9047 ///     The position of the first element in the range of elements to be combined into the resulting task.
9048 /// </param>
9049 /// <param name="_End">
9050 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
9051 /// </param>
9052 /// <returns>
9053 ///     A task that completes successfully when any one of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9054 ///     the output of this function will be a <c>task&lt;std::pair&lt;T, size_t&gt;&gt;></c>, where the first element of the pair is the result
9055 ///     of the completing task, and the second element is the index of the task that finished. If the input tasks are of type <c>void</c>
9056 ///     the output is a <c>task&lt;size_t&gt;</c>, where the result is the index of the completing task.
9057 /// </returns>
9058 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9059 /**/
9060 template<typename _Iterator>
9061 #if _MSC_VER >= 1800
9062 auto when_any(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
9063 -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
9064 {
9065     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
9066     return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
9067 }
9068 #else
9069 auto when_any(_Iterator _Begin, _Iterator _End)
9070 -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(nullptr, _Begin, _End))
9071 {
9072     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
9073     return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(nullptr, _Begin, _End);
9074 }
9075 #endif
9076 
9077 /// <summary>
9078 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes successfully.
9079 /// </summary>
9080 /// <typeparam name="_Iterator">
9081 ///     The type of the input iterator.
9082 /// </typeparam>
9083 /// <param name="_Begin">
9084 ///     The position of the first element in the range of elements to be combined into the resulting task.
9085 /// </param>
9086 /// <param name="_End">
9087 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
9088 /// </param>
9089 /// <param name="_CancellationToken">
9090 ///     The cancellation token which controls cancellation of the returned task. If you do not provide a cancellation token, the resulting
9091 ///     task will receive the cancellation token of the task that causes it to complete.
9092 /// </param>
9093 /// <returns>
9094 ///     A task that completes successfully when any one of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9095 ///     the output of this function will be a <c>task&lt;std::pair&lt;T, size_t&gt;&gt;></c>, where the first element of the pair is the result
9096 ///     of the completing task, and the second element is the index of the task that finished. If the input tasks are of type <c>void</c>
9097 ///     the output is a <c>task&lt;size_t&gt;</c>, where the result is the index of the completing task.
9098 /// </returns>
9099 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9100 /**/
9101 template<typename _Iterator>
9102 auto when_any(_Iterator _Begin, _Iterator _End, Concurrency::cancellation_token _CancellationToken)
9103 -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End))
9104 {
9105     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
9106     return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End);
9107 }
9108 
9109 /// <summary>
9110 ///     Creates a task that will complete successfully when either of the tasks supplied as arguments completes successfully.
9111 /// </summary>
9112 /// <typeparam name="_ReturnType">
9113 ///     The type of the returned task.
9114 /// </typeparam>
9115 /// <param name="_Lhs">
9116 ///     The first task to combine into the resulting task.
9117 /// </param>
9118 /// <param name="_Rhs">
9119 ///     The second task to combine into the resulting task.
9120 /// </param>
9121 /// <returns>
9122 ///     A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9123 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input tasks are of type <c>void</c> the output task
9124 ///     will also be a <c>task&lt;void&gt;</c>.
9125 ///     <para> To allow for a construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking precedence
9126 ///     over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>
9127 ///     and the other one is of type <c>task&lt;T&gt;.</para>
9128 /// </returns>
9129 /// <remarks>
9130 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state, and one of the exceptions,
9131 ///     if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on that task.
9132 /// </remarks>
9133 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9134 /**/
9135 template<typename _ReturnType>
9136 task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
9137 {
9138 #if _MSC_VER >= 1800
9139     auto _PParam = new details::_RunAnyParam<std::pair<_ReturnType, size_t>>();
9140 
9141     task<std::pair<_ReturnType, size_t>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
9142     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
9143     // So that _PParam can be used before it getting deleted.
9144     auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<_ReturnType, size_t> _Ret, _ReturnType* retVal) -> HRESULT {
9145         _CONCRT_ASSERT(_Ret.second);
9146         details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, reinterpret_cast<Concurrency::details::_CancellationTokenState *>(_Ret.second));
9147         *retVal = _Ret.first;
9148         return S_OK;
9149     }, nullptr);
9150 #else
9151     auto _PParam = new details::_RunAnyParam<std::pair<_ReturnType, Concurrency::details::_CancellationTokenState *>>();
9152 
9153     task<std::pair<_ReturnType, Concurrency::details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
9154     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
9155     // So that _PParam can be used before it getting deleted.
9156     auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<_ReturnType, Concurrency::details::_CancellationTokenState *> _Ret, _ReturnType* retVal) -> HRESULT {
9157         _CONCRT_ASSERT(_Ret.second);
9158         details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
9159         *retVal = _Ret.first;
9160         return S_OK;
9161     }, nullptr, false);
9162 #endif
9163     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
9164     {
9165         _ReturnTask._SetAsync();
9166     }
9167 
9168     _PParam->_M_numTasks = 2;
9169     auto _Continuation = [_PParam](task<_ReturnType> _ResultTask) -> HRESULT {
9170 #if _MSC_VER >= 1800
9171         //  Dev10 compiler bug
9172         auto _PParamCopy = _PParam;
9173         auto _Func = [&_ResultTask, _PParamCopy]() {
9174             _PParamCopy->_M_Completed.set(std::make_pair(_ResultTask._GetImpl()->_GetResult(), reinterpret_cast<size_t>(_ResultTask._GetImpl()->_M_pTokenState)));
9175         };
9176 #else
9177         auto _Func = [&_ResultTask, _PParam]() {
9178             _PParam->_M_Completed.set(std::make_pair(_ResultTask._GetImpl()->_GetResult(), _ResultTask._GetImpl()->_M_pTokenState));
9179         };
9180 #endif
9181         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
9182         return S_OK;
9183     };
9184 
9185 #if _MSC_VER >= 1800
9186     _Lhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None());
9187     _Rhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None());
9188 #else
9189     _Lhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None(), false);
9190     _Rhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None(), false);
9191 #endif
9192     return _ReturnTask;
9193 }
9194 
9195 /// <summary>
9196 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes successfully.
9197 /// </summary>
9198 /// <typeparam name="_ReturnType">
9199 ///     The type of the returned task.
9200 /// </typeparam>
9201 /// <param name="_Lhs">
9202 ///     The first task to combine into the resulting task.
9203 /// </param>
9204 /// <param name="_Rhs">
9205 ///     The second task to combine into the resulting task.
9206 /// </param>
9207 /// <returns>
9208 ///     A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9209 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input tasks are of type <c>void</c> the output task
9210 ///     will also be a <c>task&lt;void&gt;</c>.
9211 ///     <para> To allow for a construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking precedence
9212 ///     over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>
9213 ///     and the other one is of type <c>task&lt;T&gt;.</para>
9214 /// </returns>
9215 /// <remarks>
9216 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state, and one of the exceptions,
9217 ///     if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on that task.
9218 /// </remarks>
9219 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9220 /**/
9221 template<typename _ReturnType>
9222 task<std::vector<_ReturnType>> operator||(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
9223 {
9224     auto _PParam = new details::_RunAnyParam<std::pair<std::vector<_ReturnType>, Concurrency::details::_CancellationTokenState *>>();
9225 
9226     task<std::pair<std::vector<_ReturnType>, Concurrency::details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
9227 #if _MSC_VER < 1800
9228     _Any_tasks_completed._GetImpl()->_M_fRuntimeAggregate = true;
9229 #endif
9230     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
9231     // So that _PParam can be used before it getting deleted.
9232     auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<std::vector<_ReturnType>, Concurrency::details::_CancellationTokenState *> _Ret, std::vector<_ReturnType>* retVal) -> HRESULT {
9233         _CONCRT_ASSERT(_Ret.second);
9234         details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
9235         *retVal = _Ret.first;
9236         return S_OK;
9237     }, nullptr, true);
9238 
9239     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
9240     {
9241         _ReturnTask._SetAsync();
9242     }
9243 
9244     _PParam->_M_numTasks = 2;
9245     _Lhs._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) -> HRESULT {
9246 #if _MSC_VER >= 1800
9247         //  Dev10 compiler bug
9248         auto _PParamCopy = _PParam;
9249         auto _Func = [&_ResultTask, _PParamCopy]() {
9250             auto _Result = _ResultTask._GetImpl()->_GetResult();
9251             _PParamCopy->_M_Completed.set(std::make_pair(_Result, _ResultTask._GetImpl()->_M_pTokenState));
9252         };
9253 #else
9254         auto _Func = [&_ResultTask, _PParam]() {
9255             std::vector<_ReturnType> _Result = _ResultTask._GetImpl()->_GetResult();
9256             _PParam->_M_Completed.set(std::make_pair(_Result, _ResultTask._GetImpl()->_M_pTokenState));
9257         };
9258 #endif
9259         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
9260         return S_OK;
9261 #if _MSC_VER >= 1800
9262     }, Concurrency::details::_CancellationTokenState::_None());
9263 #else
9264     }, Concurrency::details::_CancellationTokenState::_None(), false);
9265 #endif
9266     _Rhs._Then([_PParam](task<_ReturnType> _ResultTask) -> HRESULT {
9267 #if _MSC_VER >= 1800
9268         //  Dev10 compiler bug
9269         typedef _ReturnType _ReturnTypeDev10;
9270         auto _PParamCopy = _PParam;
9271         auto _Func = [&_ResultTask, _PParamCopy]() {
9272             auto _Result = _ResultTask._GetImpl()->_GetResult();
9273 
9274             std::vector<_ReturnTypeDev10> _Vec;
9275             _Vec.push_back(_Result);
9276             _PParamCopy->_M_Completed.set(std::make_pair(_Vec, _ResultTask._GetImpl()->_M_pTokenState));
9277         };
9278 #else
9279         auto _Func = [&_ResultTask, _PParam]() {
9280             _ReturnType _Result = _ResultTask._GetImpl()->_GetResult();
9281 
9282             std::vector<_ReturnType> _Vec;
9283             _Vec.push_back(_Result);
9284             _PParam->_M_Completed.set(std::make_pair(_Vec, _ResultTask._GetImpl()->_M_pTokenState));
9285         };
9286 #endif
9287         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
9288         return S_OK;
9289 #if _MSC_VER >= 1800
9290     }, Concurrency::details::_CancellationTokenState::_None());
9291 #else
9292     }, Concurrency::details::_CancellationTokenState::_None(), false);
9293 #endif
9294     return _ReturnTask;
9295 }
9296 
9297 /// <summary>
9298 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes successfully.
9299 /// </summary>
9300 /// <typeparam name="_ReturnType">
9301 ///     The type of the returned task.
9302 /// </typeparam>
9303 /// <param name="_Lhs">
9304 ///     The first task to combine into the resulting task.
9305 /// </param>
9306 /// <param name="_Rhs">
9307 ///     The second task to combine into the resulting task.
9308 /// </param>
9309 /// <returns>
9310 ///     A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9311 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input tasks are of type <c>void</c> the output task
9312 ///     will also be a <c>task&lt;void&gt;</c>.
9313 ///     <para> To allow for a construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking precedence
9314 ///     over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>
9315 ///     and the other one is of type <c>task&lt;T&gt;.</para>
9316 /// </returns>
9317 /// <remarks>
9318 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state, and one of the exceptions,
9319 ///     if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on that task.
9320 /// </remarks>
9321 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9322 /**/
9323 template<typename _ReturnType>
9324 task<std::vector<_ReturnType>> operator||(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
9325 {
9326     return _Rhs || _Lhs;
9327 }
9328 
9329 /// <summary>
9330 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes successfully.
9331 /// </summary>
9332 /// <typeparam name="_ReturnType">
9333 ///     The type of the returned task.
9334 /// </typeparam>
9335 /// <param name="_Lhs">
9336 ///     The first task to combine into the resulting task.
9337 /// </param>
9338 /// <param name="_Rhs">
9339 ///     The second task to combine into the resulting task.
9340 /// </param>
9341 /// <returns>
9342 ///     A task that completes sucessfully when either of the input tasks has completed successfully. If the input tasks are of type <c>T</c>,
9343 ///     the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input tasks are of type <c>void</c> the output task
9344 ///     will also be a <c>task&lt;void&gt;</c>.
9345 ///     <para> To allow for a construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking precedence
9346 ///     over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of type <c>task&lt;std::vector&lt;T&gt;&gt;</c>
9347 ///     and the other one is of type <c>task&lt;T&gt;.</para>
9348 /// </returns>
9349 /// <remarks>
9350 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state, and one of the exceptions,
9351 ///     if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on that task.
9352 /// </remarks>
9353 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
9354 /**/
9355 inline task<void> operator||(const task<void> & _Lhs, const task<void> & _Rhs)
9356 {
9357     auto _PParam = new details::_RunAnyParam<std::pair<details::_Unit_type, Concurrency::details::_CancellationTokenState *>>();
9358 
9359     task<std::pair<details::_Unit_type, Concurrency::details::_CancellationTokenState *>> _Any_task_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
9360     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
9361     // So that _PParam can be used before it getting deleted.
9362     auto _ReturnTask = _Any_task_completed._Then([=](std::pair<details::_Unit_type, Concurrency::details::_CancellationTokenState *> _Ret) -> HRESULT {
9363         _CONCRT_ASSERT(_Ret.second);
9364         details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
9365         return S_OK;
9366 #if _MSC_VER >= 1800
9367     }, nullptr);
9368 #else
9369     }, nullptr, false);
9370 #endif
9371 
9372     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
9373     {
9374         _ReturnTask._SetAsync();
9375     }
9376 
9377     _PParam->_M_numTasks = 2;
9378     auto _Continuation = [_PParam](task<void> _ResultTask) mutable -> HRESULT {
9379         //  Dev10 compiler needs this.
9380         auto _PParam1 = _PParam;
9381         auto _Func = [&_ResultTask, _PParam1]() {
9382             _PParam1->_M_Completed.set(std::make_pair(details::_Unit_type(), _ResultTask._GetImpl()->_M_pTokenState));
9383         };
9384         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
9385         return S_OK;
9386     };
9387 
9388 #if _MSC_VER >= 1800
9389     _Lhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None());
9390     _Rhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None());
9391 #else
9392     _Lhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None(), false);
9393     _Rhs._Then(_Continuation, Concurrency::details::_CancellationTokenState::_None(), false);
9394 #endif
9395 
9396     return _ReturnTask;
9397 }
9398 
9399 #if _MSC_VER >= 1800
9400 template<typename _Ty>
9401 task<_Ty> task_from_result(_Ty _Param, const task_options& _TaskOptions = task_options())
9402 {
9403     task_completion_event<_Ty> _Tce;
9404     _Tce.set(_Param);
9405     return create_task<_Ty>(_Tce, _TaskOptions);
9406 }
9407 
9408 // Work around VS 2010 compiler bug
9409 #if _MSC_VER == 1600
9410 inline task<bool> task_from_result(bool _Param)
9411 {
9412     task_completion_event<bool> _Tce;
9413     _Tce.set(_Param);
9414     return create_task<bool>(_Tce, task_options());
9415 }
9416 #endif
9417 inline task<void> task_from_result(const task_options& _TaskOptions = task_options())
9418 {
9419     task_completion_event<void> _Tce;
9420     _Tce.set();
9421     return create_task<void>(_Tce, _TaskOptions);
9422 }
9423 
9424 template<typename _TaskType, typename _ExType>
9425 task<_TaskType> task_from_exception(_ExType _Exception, const task_options& _TaskOptions = task_options())
9426 {
9427     task_completion_event<_TaskType> _Tce;
9428     _Tce.set_exception(_Exception);
9429     return create_task<_TaskType>(_Tce, _TaskOptions);
9430 }
9431 
9432 namespace details
9433 {
9434     /// <summary>
9435     /// A convenient extension to Concurrency: loop until a condition is no longer met
9436     /// </summary>
9437     /// <param name="func">
9438     ///   A function representing the body of the loop. It will be invoked at least once and
9439     ///   then repetitively as long as it returns true.
9440     /// </param>
9441     inline
9442     task<bool> do_while(std::function<task<bool>(void)> func)
9443     {
9444             task<bool> first = func();
9445             return first.then([=](bool guard, task<bool>* retVal) -> HRESULT {
9446                 if (guard)
9447                     *retVal = do_while(func);
9448                 else
9449                     *retVal = first;
9450                 return S_OK;
9451             });
9452     }
9453 
9454 } // namespace details
9455 #endif
9456 
9457 } // namespace Concurrency_winrt
9458 
9459 namespace concurrency_winrt = Concurrency_winrt;
9460 
9461 #pragma pop_macro("new")
9462 #pragma warning(pop)
9463 #pragma pack(pop)
9464 #endif
9465 
9466 #endif
9467