1 /***
2  * Copyright (C) Microsoft. All rights reserved.
3  * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4  *
5  * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
6  *
7  * Parallel Patterns Library - PPLx Tasks
8  *
9  * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
10  *
11  * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
12  ****/
13 
14 #pragma once
15 
16 #ifndef PPLXTASKS_H
17 #define PPLXTASKS_H
18 
19 #include "cpprest/details/cpprest_compat.h"
20 
21 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
22 #include <ppltasks.h>
23 namespace pplx = Concurrency;
24 
25 namespace Concurrency
26 {
27 /// <summary>
28 /// Sets the ambient scheduler to be used by the PPL constructs.
29 /// </summary>
30 _ASYNCRTIMP void __cdecl set_cpprestsdk_ambient_scheduler(const std::shared_ptr<scheduler_interface>& _Scheduler);
31 
32 /// <summary>
33 /// Gets the ambient scheduler to be used by the PPL constructs
34 /// </summary>
35 _ASYNCRTIMP const std::shared_ptr<scheduler_interface>& __cdecl get_cpprestsdk_ambient_scheduler();
36 
37 } // namespace Concurrency
38 
39 #if (_MSC_VER >= 1900)
40 #include <concrt.h>
41 namespace Concurrency
42 {
43 namespace extensibility
44 {
45 typedef ::std::condition_variable condition_variable_t;
46 typedef ::std::mutex critical_section_t;
47 typedef ::std::unique_lock<::std::mutex> scoped_critical_section_t;
48 
49 typedef ::Concurrency::event event_t;
50 typedef ::Concurrency::reader_writer_lock reader_writer_lock_t;
51 typedef ::Concurrency::reader_writer_lock::scoped_lock scoped_rw_lock_t;
52 typedef ::Concurrency::reader_writer_lock::scoped_lock_read scoped_read_lock_t;
53 
54 typedef ::Concurrency::details::_ReentrantBlockingLock recursive_lock_t;
55 typedef recursive_lock_t::_Scoped_lock scoped_recursive_lock_t;
56 } // namespace extensibility
57 } // namespace Concurrency
58 #endif // _MSC_VER >= 1900
59 #else
60 
61 #include "pplx/pplx.h"
62 
63 #if defined(__ANDROID__)
64 #include <jni.h>
65 void cpprest_init(JavaVM*);
66 #endif
67 
68 // Cannot build using a compiler that is older than dev10 SP1
69 #if defined(_MSC_VER)
70 #if _MSC_FULL_VER < 160040219 /*IFSTRIP=IGN*/
71 #error ERROR: Visual Studio 2010 SP1 or later is required to build ppltasks
72 #endif /*IFSTRIP=IGN*/
73 #endif /* defined(_MSC_VER) */
74 
75 #include <algorithm>
76 #include <atomic>
77 #include <exception>
78 #include <functional>
79 #include <utility>
80 #include <vector>
81 
82 #if defined(_MSC_VER)
83 #include <intrin.h>
84 #if defined(__cplusplus_winrt)
85 #include <agile.h>
86 #include <ctxtcall.h>
87 #include <winapifamily.h>
88 
89 #include <windows.h>
90 #ifndef _UITHREADCTXT_SUPPORT
91 
92 #ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/
93 
94 // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user
95 #include <winapifamily.h>
96 
97 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
98 // UI thread context support is not required for desktop and Windows Store apps
99 #define _UITHREADCTXT_SUPPORT 0
100 #elif WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
101 // UI thread context support is not required for desktop and Windows Store apps
102 #define _UITHREADCTXT_SUPPORT 0
103 #else /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
104 #define _UITHREADCTXT_SUPPORT 1
105 #endif /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
106 
107 #else /* WINAPI_FAMILY */
108 // Not supported without a WINAPI_FAMILY setting.
109 #define _UITHREADCTXT_SUPPORT 0
110 #endif /* WINAPI_FAMILY */
111 
112 #endif /* _UITHREADCTXT_SUPPORT */
113 
114 #if _UITHREADCTXT_SUPPORT
115 #include <uithreadctxt.h>
116 #endif /* _UITHREADCTXT_SUPPORT */
117 
118 #pragma detect_mismatch("PPLXTASKS_WITH_WINRT", "1")
119 #else /* defined(__cplusplus_winrt) */
120 #pragma detect_mismatch("PPLXTASKS_WITH_WINRT", "0")
121 #endif /* defined(__cplusplus_winrt) */
122 #endif /* defined(_MSC_VER) */
123 
124 #ifdef _DEBUG
125 #define _DBG_ONLY(X) X
126 #else
127 #define _DBG_ONLY(X)
128 #endif // #ifdef _DEBUG
129 
130 // std::copy_exception changed to std::make_exception_ptr from VS 2010 to VS 11.
131 #ifdef _MSC_VER
132 #if _MSC_VER < 1700 /*IFSTRIP=IGN*/
133 namespace std
134 {
135 template<class _E>
make_exception_ptr(_E _Except)136 exception_ptr make_exception_ptr(_E _Except)
137 {
138     return copy_exception(_Except);
139 }
140 } // namespace std
141 #endif              /* _MSC_VER < 1700 */
142 #ifndef PPLX_TASK_ASYNC_LOGGING
143 #if _MSC_VER >= 1800 && defined(__cplusplus_winrt)
144 #define PPLX_TASK_ASYNC_LOGGING 1 // Only enable async logging under dev12 winrt
145 #else
146 #define PPLX_TASK_ASYNC_LOGGING 0
147 #endif
148 #endif /* !PPLX_TASK_ASYNC_LOGGING */
149 #endif /* _MSC_VER */
150 
151 #pragma pack(push, _CRT_PACKING)
152 
153 #if defined(_MSC_VER)
154 #pragma warning(push)
155 #pragma warning(disable : 28197)
156 #pragma warning(disable : 4100) // Unreferenced formal parameter - needed for document generation
157 #pragma warning(disable : 4127) // constant express in if condition - we use it for meta programming
158 #endif                          /* defined(_MSC_VER) */
159 
160 // All CRT public header files are required to be protected from the macro new
161 #pragma push_macro("new")
162 #undef new
163 
164 // stuff ported from Dev11 CRT
165 // NOTE: this doesn't actually match std::declval. it behaves differently for void!
166 // so don't blindly change it to std::declval.
167 namespace stdx
168 {
169 template<class _T>
170 _T&& declval();
171 }
172 
173 /// <summary>
174 ///     The <c>pplx</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
175 ///     a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
176 /// </summary>
177 /**/
178 namespace pplx
179 {
180 /// <summary>
181 ///     A type that represents the terminal state of a task. Valid values are <c>completed</c> and <c>canceled</c>.
182 /// </summary>
183 /// <seealso cref="task Class"/>
184 /**/
185 typedef task_group_status task_status;
186 
187 template<typename _Type>
188 class task;
189 template<>
190 class task<void>;
191 
192 // In debug builds, default to 10 frames, unless this is overridden prior to #includ'ing ppltasks.h.  In retail builds,
193 // default to only one frame.
194 #ifndef PPLX_TASK_SAVE_FRAME_COUNT
195 #ifdef _DEBUG
196 #define PPLX_TASK_SAVE_FRAME_COUNT 10
197 #else
198 #define PPLX_TASK_SAVE_FRAME_COUNT 1
199 #endif
200 #endif
201 
202 /// <summary>
203 /// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified,
204 /// only one frame is captured and no stackwalk will be involved. Otherwise, the number of callstack frames will be
205 /// captured.
206 /// </summary>
207 /// <ramarks>
208 /// This needs to be defined as a macro rather than a function so that if we're only gathering one frame,
209 /// _ReturnAddress() will evaluate to client code, rather than a helper function inside of _TaskCreationCallstack,
210 /// itself.
211 /// </remarks>
212 #if PPLX_TASK_SAVE_FRAME_COUNT > 1
213 #if defined(__cplusplus_winrt) && !defined(_DEBUG)
214 #pragma message(                                                                                                       \
215     "WARNING: Redefining PPLX_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!")
216 #define PPLX_CAPTURE_CALLSTACK() ::pplx::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
217 #else
218 #define PPLX_CAPTURE_CALLSTACK()                                                                                       \
219     ::pplx::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPLX_TASK_SAVE_FRAME_COUNT)
220 #endif
221 #else
222 #define PPLX_CAPTURE_CALLSTACK() ::pplx::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
223 #endif
224 
225 /// <summary>
226 ///     Returns an indication of whether the task that is currently executing has received a request to cancel its
227 ///     execution. Cancellation is requested on a task if the task was created with a cancellation token, and
228 ///     the token source associated with that token is canceled.
229 /// </summary>
230 /// <returns>
231 ///     <c>true</c> if the currently executing task has received a request for cancellation, <c>false</c> otherwise.
232 /// </returns>
233 /// <remarks>
234 ///     If you call this method in the body of a task and it returns <c>true</c>, you must respond with a call to
235 ///     <see cref="cancel_current_task Function">cancel_current_task</see> to acknowledge the cancellation request,
236 ///     after performing any cleanup you need. This will abort the execution of the task and cause it to enter into
237 ///     the <c>canceled</c> state. If you do not respond and continue execution, or return instead of calling
238 ///     <c>cancel_current_task</c>, the task will enter the <c>completed</c> state when it is done.
239 ///     state.
240 ///     <para>A task is not cancelable if it was created without a cancellation token.</para>
241 /// </remarks>
242 /// <seealso cref="task Class"/>
243 /// <seealso cref="cancellation_token_source Class"/>
244 /// <seealso cref="cancellation_token Class"/>
245 /// <seealso cref="cancel_current_task Function"/>
246 /**/
is_task_cancellation_requested()247 inline bool _pplx_cdecl is_task_cancellation_requested()
248 {
249     return ::pplx::details::_TaskCollection_t::_Is_cancellation_requested();
250 }
251 
252 /// <summary>
253 ///     Cancels the currently executing task. This function can be called from within the body of a task to abort the
254 ///     task's execution and cause it to enter the <c>canceled</c> state. While it may be used in response to
255 ///     the <see cref="is_task_cancellation_requested Function">is_task_cancellation_requested</see> function, you may
256 ///     also use it by itself, to initiate cancellation of the task that is currently executing.
257 ///     <para>It is not a supported scenario to call this function if you are not within the body of a <c>task</c>.
258 ///     Doing so will result in undefined behavior such as a crash or a hang in your application.</para>
259 /// </summary>
260 /// <seealso cref="task Class"/>
261 /**/
cancel_current_task()262 inline __declspec(noreturn) void _pplx_cdecl cancel_current_task() { throw task_canceled(); }
263 
264 namespace details
265 {
266 /// <summary>
267 ///     Callstack container, which is used to capture and preserve callstacks in ppltasks.
268 ///     Members of this class is examined by vc debugger, thus there will be no public access methods.
269 ///     Please note that names of this class should be kept stable for debugger examining.
270 /// </summary>
271 class _TaskCreationCallstack
272 {
273 private:
274     // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame;
275     // otherwise, _M_Frame will store all the callstack frames.
276     void* _M_SingleFrame;
277     std::vector<void*> _M_frames;
278 
279 public:
_TaskCreationCallstack()280     _TaskCreationCallstack() { _M_SingleFrame = nullptr; }
281 
282     // Store one frame of callstack. This function works for both Debug / Release CRT.
_CaptureSingleFrameCallstack(void * _SingleFrame)283     static _TaskCreationCallstack _CaptureSingleFrameCallstack(void* _SingleFrame)
284     {
285         _TaskCreationCallstack _csc;
286         _csc._M_SingleFrame = _SingleFrame;
287         return _csc;
288     }
289 
290     // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT.
_CaptureMultiFramesCallstack(size_t _CaptureFrames)291     __declspec(noinline) static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames)
292     {
293         _TaskCreationCallstack _csc;
294         _csc._M_frames.resize(_CaptureFrames);
295         // skip 2 frames to make sure callstack starts from user code
296         _csc._M_frames.resize(::pplx::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames));
297         return _csc;
298     }
299 };
300 typedef unsigned char _Unit_type;
301 
302 struct _TypeSelectorNoAsync
303 {
304 };
305 struct _TypeSelectorAsyncOperationOrTask
306 {
307 };
308 struct _TypeSelectorAsyncOperation : public _TypeSelectorAsyncOperationOrTask
309 {
310 };
311 struct _TypeSelectorAsyncTask : public _TypeSelectorAsyncOperationOrTask
312 {
313 };
314 struct _TypeSelectorAsyncAction
315 {
316 };
317 struct _TypeSelectorAsyncActionWithProgress
318 {
319 };
320 struct _TypeSelectorAsyncOperationWithProgress
321 {
322 };
323 
324 template<typename _Ty>
325 struct _NormalizeVoidToUnitType
326 {
327     typedef _Ty _Type;
328 };
329 
330 template<>
331 struct _NormalizeVoidToUnitType<void>
332 {
333     typedef _Unit_type _Type;
334 };
335 
336 template<typename _T>
337 struct _IsUnwrappedAsyncSelector
338 {
339     static const bool _Value = true;
340 };
341 
342 template<>
343 struct _IsUnwrappedAsyncSelector<_TypeSelectorNoAsync>
344 {
345     static const bool _Value = false;
346 };
347 
348 template<typename _Ty>
349 struct _UnwrapTaskType
350 {
351     typedef _Ty _Type;
352 };
353 
354 template<typename _Ty>
355 struct _UnwrapTaskType<task<_Ty>>
356 {
357     typedef _Ty _Type;
358 };
359 
360 template<typename _T>
361 _TypeSelectorAsyncTask _AsyncOperationKindSelector(task<_T>);
362 
363 _TypeSelectorNoAsync _AsyncOperationKindSelector(...);
364 
365 #if defined(__cplusplus_winrt)
366 template<typename _Type>
367 struct _Unhat
368 {
369     typedef _Type _Value;
370 };
371 
372 template<typename _Type>
373 struct _Unhat<_Type ^>
374 {
375     typedef _Type _Value;
376 };
377 
378 value struct _NonUserType
379 {
380 public:
381     int _Dummy;
382 };
383 
384 template<typename _Type, bool _IsValueTypeOrRefType = __is_valid_winrt_type(_Type)>
385 struct _ValueTypeOrRefType
386 {
387     typedef _NonUserType _Value;
388 };
389 
390 template<typename _Type>
391 struct _ValueTypeOrRefType<_Type, true>
392 {
393     typedef _Type _Value;
394 };
395 
396 template<typename _T1, typename _T2>
397 _T2 _ProgressTypeSelector(Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2> ^);
398 
399 template<typename _T1>
400 _T1 _ProgressTypeSelector(Windows::Foundation::IAsyncActionWithProgress<_T1> ^);
401 
402 template<typename _Type>
403 struct _GetProgressType
404 {
405     typedef decltype(_ProgressTypeSelector(stdx::declval<_Type>())) _Value;
406 };
407 
408 template<typename _Type>
409 struct _IsIAsyncInfo
410 {
411     static const bool _Value = __is_base_of(Windows::Foundation::IAsyncInfo, typename _Unhat<_Type>::_Value);
412 };
413 
414 template<typename _T>
415 _TypeSelectorAsyncOperation _AsyncOperationKindSelector(Windows::Foundation::IAsyncOperation<_T> ^);
416 
417 _TypeSelectorAsyncAction _AsyncOperationKindSelector(Windows::Foundation::IAsyncAction ^);
418 
419 template<typename _T1, typename _T2>
420 _TypeSelectorAsyncOperationWithProgress _AsyncOperationKindSelector(
421     Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2> ^);
422 
423 template<typename _T>
424 _TypeSelectorAsyncActionWithProgress _AsyncOperationKindSelector(Windows::Foundation::IAsyncActionWithProgress<_T> ^);
425 
426 template<typename _Type, bool _IsAsync = _IsIAsyncInfo<_Type>::_Value>
427 struct _TaskTypeTraits
428 {
429     typedef typename _UnwrapTaskType<_Type>::_Type _TaskRetType;
430     typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
431     typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
432 
433     static const bool _IsAsyncTask = _IsAsync;
434     static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
435 };
436 
437 template<typename _Type>
438 struct _TaskTypeTraits<_Type, true>
439 {
440     typedef decltype(((_Type) nullptr)->GetResults()) _TaskRetType;
441     typedef _TaskRetType _NormalizedTaskRetType;
442     typedef decltype(_AsyncOperationKindSelector((_Type) nullptr)) _AsyncKind;
443 
444     static const bool _IsAsyncTask = true;
445     static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
446 };
447 
448 #else  /* defined (__cplusplus_winrt) */
449 template<typename _Type>
450 struct _IsIAsyncInfo
451 {
452     static const bool _Value = false;
453 };
454 
455 template<typename _Type, bool _IsAsync = false>
456 struct _TaskTypeTraits
457 {
458     typedef typename _UnwrapTaskType<_Type>::_Type _TaskRetType;
459     typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
460     typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
461 
462     static const bool _IsAsyncTask = false;
463     static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
464 };
465 #endif /* defined (__cplusplus_winrt) */
466 
467 template<typename _Function>
468 auto _IsCallable(_Function _Func, int) -> decltype(_Func(), std::true_type())
469 {
470     (void)(_Func);
471     return std::true_type();
472 }
473 template<typename _Function>
474 std::false_type _IsCallable(_Function, ...)
475 {
476     return std::false_type();
477 }
478 
479 template<>
480 struct _TaskTypeTraits<void>
481 {
482     typedef void _TaskRetType;
483     typedef _TypeSelectorNoAsync _AsyncKind;
484     typedef _Unit_type _NormalizedTaskRetType;
485 
486     static const bool _IsAsyncTask = false;
487     static const bool _IsUnwrappedTaskOrAsync = false;
488 };
489 
490 template<typename _Type>
491 task<_Type> _To_task(_Type t);
492 
493 template<typename _Func>
494 task<void> _To_task_void(_Func f);
495 
496 struct _BadContinuationParamType
497 {
498 };
499 
500 template<typename _Function, typename _Type>
501 auto _ReturnTypeHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)));
502 template<typename _Function, typename _Type>
503 auto _ReturnTypeHelper(_Type t, _Function _Func, int, ...) -> decltype(_Func(t));
504 template<typename _Function, typename _Type>
505 auto _ReturnTypeHelper(_Type t, _Function _Func, ...) -> _BadContinuationParamType;
506 
507 template<typename _Function, typename _Type>
508 auto _IsTaskHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)), std::true_type());
509 template<typename _Function, typename _Type>
510 std::false_type _IsTaskHelper(_Type t, _Function _Func, int, ...);
511 
512 template<typename _Function>
513 auto _VoidReturnTypeHelper(_Function _Func, int, int) -> decltype(_Func(_To_task_void(_Func)));
514 template<typename _Function>
515 auto _VoidReturnTypeHelper(_Function _Func, int, ...) -> decltype(_Func());
516 
517 template<typename _Function>
518 auto _VoidIsTaskHelper(_Function _Func, int, int) -> decltype(_Func(_To_task_void(_Func)), std::true_type());
519 template<typename _Function>
520 std::false_type _VoidIsTaskHelper(_Function _Func, int, ...);
521 
522 template<typename _Function, typename _ExpectedParameterType>
523 struct _FunctionTypeTraits
524 {
525     typedef decltype(
526         _ReturnTypeHelper(stdx::declval<_ExpectedParameterType>(), stdx::declval<_Function>(), 0, 0)) _FuncRetType;
527     static_assert(!std::is_same<_FuncRetType, _BadContinuationParamType>::value,
528                   "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or "
529                   "task<_ExpectedParameterType> (see below)");
530 
531     typedef decltype(
532         _IsTaskHelper(stdx::declval<_ExpectedParameterType>(), stdx::declval<_Function>(), 0, 0)) _Takes_task;
533 };
534 
535 template<typename _Function>
536 struct _FunctionTypeTraits<_Function, void>
537 {
538     typedef decltype(_VoidReturnTypeHelper(stdx::declval<_Function>(), 0, 0)) _FuncRetType;
539     typedef decltype(_VoidIsTaskHelper(stdx::declval<_Function>(), 0, 0)) _Takes_task;
540 };
541 
542 template<typename _Function, typename _ReturnType>
543 struct _ContinuationTypeTraits
544 {
545     typedef task<
546         typename _TaskTypeTraits<typename _FunctionTypeTraits<_Function, _ReturnType>::_FuncRetType>::_TaskRetType>
547         _TaskOfType;
548 };
549 
550 // _InitFunctorTypeTraits is used to decide whether a task constructed with a lambda should be unwrapped. Depending on
551 // how the variable is declared, the constructor may or may not perform unwrapping. For eg.
552 //
553 //  This declaration SHOULD NOT cause unwrapping
554 //    task<task<void>> t1([]() -> task<void> {
555 //        task<void> t2([]() {});
556 //        return t2;
557 //    });
558 //
559 // This declaration SHOULD cause unwrapping
560 //    task<void>> t1([]() -> task<void> {
561 //        task<void> t2([]() {});
562 //        return t2;
563 //    });
564 // If the type of the task is the same as the return type of the function, no unwrapping should take place. Else normal
565 // rules apply.
566 template<typename _TaskType, typename _FuncRetType>
567 struct _InitFunctorTypeTraits
568 {
569     typedef typename _TaskTypeTraits<_FuncRetType>::_AsyncKind _AsyncKind;
570     static const bool _IsAsyncTask = _TaskTypeTraits<_FuncRetType>::_IsAsyncTask;
571     static const bool _IsUnwrappedTaskOrAsync = _TaskTypeTraits<_FuncRetType>::_IsUnwrappedTaskOrAsync;
572 };
573 
574 template<typename T>
575 struct _InitFunctorTypeTraits<T, T>
576 {
577     typedef _TypeSelectorNoAsync _AsyncKind;
578     static const bool _IsAsyncTask = false;
579     static const bool _IsUnwrappedTaskOrAsync = false;
580 };
581 
582 /// <summary>
583 ///     Helper object used for LWT invocation.
584 /// </summary>
585 struct _TaskProcThunk
586 {
587     _TaskProcThunk(const std::function<void()>& _Callback) : _M_func(_Callback) {}
588 
589     static void _pplx_cdecl _Bridge(void* _PData)
590     {
591         _TaskProcThunk* _PThunk = reinterpret_cast<_TaskProcThunk*>(_PData);
592         _Holder _ThunkHolder(_PThunk);
593         _PThunk->_M_func();
594     }
595 
596 private:
597     // RAII holder
598     struct _Holder
599     {
600         _Holder(_TaskProcThunk* _PThunk) : _M_pThunk(_PThunk) {}
601 
602         ~_Holder() { delete _M_pThunk; }
603 
604         _TaskProcThunk* _M_pThunk;
605 
606     private:
607         _Holder& operator=(const _Holder&);
608     };
609 
610     std::function<void()> _M_func;
611     _TaskProcThunk& operator=(const _TaskProcThunk&);
612 };
613 
614 /// <summary>
615 ///     Schedule a functor with automatic inlining. Note that this is "fire and forget" scheduling, which cannot be
616 ///     waited on or canceled after scheduling.
617 ///     This schedule method will perform automatic inlining base on <paramref value="_InliningMode"/>.
618 /// </summary>
619 /// <param name="_Func">
620 ///     The user functor need to be scheduled.
621 /// </param>
622 /// <param name="_InliningMode">
623 ///     The inlining scheduling policy for current functor.
624 /// </param>
625 static void _ScheduleFuncWithAutoInline(const std::function<void()>& _Func, _TaskInliningMode_t _InliningMode)
626 {
627     _TaskCollection_t::_RunTask(&_TaskProcThunk::_Bridge, new _TaskProcThunk(_Func), _InliningMode);
628 }
629 
630 class _ContextCallback
631 {
632     typedef std::function<void(void)> _CallbackFunction;
633 
634 #if defined(__cplusplus_winrt)
635 
636 public:
637     static _ContextCallback _CaptureCurrent()
638     {
639         _ContextCallback _Context;
640         _Context._Capture();
641         return _Context;
642     }
643 
644     ~_ContextCallback() { _Reset(); }
645 
646     _ContextCallback(bool _DeferCapture = false)
647     {
648         if (_DeferCapture)
649         {
650             _M_context._M_captureMethod = _S_captureDeferred;
651         }
652         else
653         {
654             _M_context._M_pContextCallback = nullptr;
655         }
656     }
657 
658     // Resolves a context that was created as _S_captureDeferred based on the environment (ancestor, current context).
659     void _Resolve(bool _CaptureCurrent)
660     {
661         if (_M_context._M_captureMethod == _S_captureDeferred)
662         {
663             _M_context._M_pContextCallback = nullptr;
664 
665             if (_CaptureCurrent)
666             {
667                 if (_IsCurrentOriginSTA())
668                 {
669                     _Capture();
670                 }
671 #if _UITHREADCTXT_SUPPORT
672                 else
673                 {
674                     // This method will fail if not called from the UI thread.
675                     HRESULT _Hr = CaptureUiThreadContext(&_M_context._M_pContextCallback);
676                     if (FAILED(_Hr))
677                     {
678                         _M_context._M_pContextCallback = nullptr;
679                     }
680                 }
681 #endif /* _UITHREADCTXT_SUPPORT */
682             }
683         }
684     }
685 
686     void _Capture()
687     {
688         HRESULT _Hr =
689             CoGetObjectContext(IID_IContextCallback, reinterpret_cast<void**>(&_M_context._M_pContextCallback));
690         if (FAILED(_Hr))
691         {
692             _M_context._M_pContextCallback = nullptr;
693         }
694     }
695 
696     _ContextCallback(const _ContextCallback& _Src) { _Assign(_Src._M_context._M_pContextCallback); }
697 
698     _ContextCallback(_ContextCallback&& _Src)
699     {
700         _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
701         _Src._M_context._M_pContextCallback = nullptr;
702     }
703 
704     _ContextCallback& operator=(const _ContextCallback& _Src)
705     {
706         if (this != &_Src)
707         {
708             _Reset();
709             _Assign(_Src._M_context._M_pContextCallback);
710         }
711         return *this;
712     }
713 
714     _ContextCallback& operator=(_ContextCallback&& _Src)
715     {
716         if (this != &_Src)
717         {
718             _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
719             _Src._M_context._M_pContextCallback = nullptr;
720         }
721         return *this;
722     }
723 
724     bool _HasCapturedContext() const
725     {
726         _ASSERTE(_M_context._M_captureMethod != _S_captureDeferred);
727         return (_M_context._M_pContextCallback != nullptr);
728     }
729 
730     void _CallInContext(_CallbackFunction _Func) const
731     {
732         if (!_HasCapturedContext())
733         {
734             _Func();
735         }
736         else
737         {
738             ComCallData callData;
739             ZeroMemory(&callData, sizeof(callData));
740             callData.pUserDefined = reinterpret_cast<void*>(&_Func);
741 
742             HRESULT _Hr = _M_context._M_pContextCallback->ContextCallback(
743                 &_Bridge, &callData, IID_ICallbackWithNoReentrancyToApplicationSTA, 5, nullptr);
744             if (FAILED(_Hr))
745             {
746                 throw ::Platform::Exception::CreateException(_Hr);
747             }
748         }
749     }
750 
751     bool operator==(const _ContextCallback& _Rhs) const
752     {
753         return (_M_context._M_pContextCallback == _Rhs._M_context._M_pContextCallback);
754     }
755 
756     bool operator!=(const _ContextCallback& _Rhs) const { return !(operator==(_Rhs)); }
757 
758 private:
759     void _Reset()
760     {
761         if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
762         {
763             _M_context._M_pContextCallback->Release();
764         }
765     }
766 
767     void _Assign(IContextCallback* _PContextCallback)
768     {
769         _M_context._M_pContextCallback = _PContextCallback;
770         if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
771         {
772             _M_context._M_pContextCallback->AddRef();
773         }
774     }
775 
776     static HRESULT __stdcall _Bridge(ComCallData* _PParam)
777     {
778         _CallbackFunction* pFunc = reinterpret_cast<_CallbackFunction*>(_PParam->pUserDefined);
779         (*pFunc)();
780         return S_OK;
781     }
782 
783     // Returns the origin information for the caller (runtime / Windows Runtime apartment as far as task continuations
784     // need know)
785     static bool _IsCurrentOriginSTA()
786     {
787         APTTYPE _AptType;
788         APTTYPEQUALIFIER _AptTypeQualifier;
789 
790         HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
791         if (SUCCEEDED(hr))
792         {
793             // We determine the origin of a task continuation by looking at where .then is called, so we can tell
794             // whether to need to marshal the continuation back to the originating apartment. If an STA thread is in
795             // executing in a neutral apartment when it schedules a continuation, we will not marshal continuations back
796             // to the STA, since variables used within a neutral apartment are expected to be apartment neutral.
797             switch (_AptType)
798             {
799                 case APTTYPE_MAINSTA:
800                 case APTTYPE_STA: return true;
801                 default: break;
802             }
803         }
804         return false;
805     }
806 
807     union {
808         IContextCallback* _M_pContextCallback;
809         size_t _M_captureMethod;
810     } _M_context;
811 
812     static const size_t _S_captureDeferred = 1;
813 #else  /* defined (__cplusplus_winrt) */
814 public:
815     static _ContextCallback _CaptureCurrent() { return _ContextCallback(); }
816 
817     _ContextCallback(bool = false) {}
818 
819     _ContextCallback(const _ContextCallback&) {}
820 
821     _ContextCallback(_ContextCallback&&) {}
822 
823     _ContextCallback& operator=(const _ContextCallback&) { return *this; }
824 
825     _ContextCallback& operator=(_ContextCallback&&) { return *this; }
826 
827     bool _HasCapturedContext() const { return false; }
828 
829     void _Resolve(bool) const {}
830 
831     void _CallInContext(_CallbackFunction _Func) const { _Func(); }
832 
833     bool operator==(const _ContextCallback&) const { return true; }
834 
835     bool operator!=(const _ContextCallback&) const { return false; }
836 
837 #endif /* defined (__cplusplus_winrt) */
838 };
839 
840 template<typename _Type>
841 struct _ResultHolder
842 {
843     void Set(const _Type& _type) { _Result = _type; }
844 
845     _Type Get() { return _Result; }
846 
847     _Type _Result;
848 };
849 
850 #if defined(__cplusplus_winrt)
851 
852 template<typename _Type>
853 struct _ResultHolder<_Type ^>
854 {
855     void Set(_Type ^ const& _type) { _M_Result = _type; }
856 
857     _Type ^ Get() { return _M_Result.Get(); } private :
858         // ::Platform::Agile handle specialization of all hats
859         // including ::Platform::String and ::Platform::Array
860         ::Platform::Agile<_Type ^> _M_Result;
861 };
862 
863 //
864 // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs.
865 //
866 template<typename _Type>
867 struct _ResultHolder<std::vector<_Type ^>>
868 {
869     void Set(const std::vector<_Type ^>& _type)
870     {
871         _Result.reserve(_type.size());
872 
873         for (auto _PTask = _type.begin(); _PTask != _type.end(); ++_PTask)
874         {
875             _Result.emplace_back(*_PTask);
876         }
877     }
878 
879     std::vector<_Type ^> Get()
880     {
881         // Return vectory<T^> with the objects that are marshaled in the proper apartment
882         std::vector<_Type ^> _Return;
883         _Return.reserve(_Result.size());
884 
885         for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask)
886         {
887             _Return.push_back(
888                 _PTask->Get()); // Platform::Agile will marshal the object to appropriate apartment if necessary
889         }
890 
891         return _Return;
892     }
893 
894     std::vector<::Platform::Agile<_Type ^>> _Result;
895 };
896 
897 template<typename _Type>
898 struct _ResultHolder<std::pair<_Type ^, void*>>
899 {
900     void Set(const std::pair<_Type ^, size_t>& _type) { _M_Result = _type; }
901 
902     std::pair<_Type ^, size_t> Get() { return std::make_pair(_M_Result.first.Get(), _M_Result.second); }
903 
904 private:
905     std::pair<::Platform::Agile<_Type ^>, size_t> _M_Result;
906 };
907 
908 #endif /* defined (__cplusplus_winrt) */
909 
910 // An exception thrown by the task body is captured in an exception holder and it is shared with all value based
911 // continuations rooted at the task. The exception is 'observed' if the user invokes get()/wait() on any of the tasks
912 // that are sharing this exception holder. If the exception is not observed by the time the internal object owned by the
913 // shared pointer destructs, the process will fail fast.
914 struct _ExceptionHolder
915 {
916 private:
917     void ReportUnhandledError()
918     {
919 #if _MSC_VER >= 1800 && defined(__cplusplus_winrt)
920         if (_M_winRTException != nullptr)
921         {
922             ::Platform::Details::ReportUnhandledError(_M_winRTException);
923         }
924 #endif /* defined (__cplusplus_winrt) */
925     }
926 
927 public:
928     explicit _ExceptionHolder(const std::exception_ptr& _E, const _TaskCreationCallstack& _stackTrace)
929         : _M_exceptionObserved(0)
930         , _M_stdException(_E)
931         , _M_stackTrace(_stackTrace)
932 #if defined(__cplusplus_winrt)
933         , _M_winRTException(nullptr)
934 #endif /* defined (__cplusplus_winrt) */
935     {
936     }
937 
938 #if defined(__cplusplus_winrt)
939     explicit _ExceptionHolder(::Platform::Exception ^ _E, const _TaskCreationCallstack& _stackTrace)
940         : _M_exceptionObserved(0), _M_winRTException(_E), _M_stackTrace(_stackTrace)
941     {
942     }
943 #endif /* defined (__cplusplus_winrt) */
944 
945     __declspec(noinline) ~_ExceptionHolder()
946     {
947         if (_M_exceptionObserved == 0)
948         {
949             // If you are trapped here, it means an exception thrown in task chain didn't get handled.
950             // Please add task-based continuation to handle all exceptions coming from tasks.
951             // this->_M_stackTrace keeps the creation callstack of the task generates this exception.
952             _REPORT_PPLTASK_UNOBSERVED_EXCEPTION();
953         }
954     }
955 
956     void _RethrowUserException()
957     {
958         if (_M_exceptionObserved == 0)
959         {
960             atomic_exchange(_M_exceptionObserved, 1l);
961         }
962 
963 #if defined(__cplusplus_winrt)
964         if (_M_winRTException != nullptr)
965         {
966             throw _M_winRTException;
967         }
968 #endif /* defined (__cplusplus_winrt) */
969         std::rethrow_exception(_M_stdException);
970     }
971 
972     // A variable that remembers if this exception was every rethrown into user code (and hence handled by the user).
973     // Exceptions that are unobserved when the exception holder is destructed will terminate the process.
974     atomic_long _M_exceptionObserved;
975 
976     // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered.
977     std::exception_ptr _M_stdException;
978 #if defined(__cplusplus_winrt)
979     ::Platform::Exception ^ _M_winRTException;
980 #endif /* defined (__cplusplus_winrt) */
981 
982     // Disassembling this value will point to a source instruction right after a call instruction. If the call is to
983     // create_task, a task constructor or the then method, the task created by that method is the one that encountered
984     // this exception. If the call is to task_completion_event::set_exception, the set_exception method was the source
985     // of the exception. DO NOT REMOVE THIS VARIABLE. It is extremely helpful for debugging.
986     _TaskCreationCallstack _M_stackTrace;
987 };
988 
989 #if defined(__cplusplus_winrt)
990 /// <summary>
991 ///     Base converter class for converting asynchronous interfaces to IAsyncOperation
992 /// </summary>
993 template<typename _AsyncOperationType, typename _CompletionHandlerType, typename _Result>
994 ref struct _AsyncInfoImpl abstract : Windows::Foundation::IAsyncOperation<_Result>
995 {
996     internal :
997         // The async action, action with progress or operation with progress that this stub forwards to.
998         ::Platform::Agile<_AsyncOperationType>
999             _M_asyncInfo;
1000 
1001     Windows::Foundation::AsyncOperationCompletedHandler<_Result> ^ _M_CompletedHandler;
1002 
1003     _AsyncInfoImpl(_AsyncOperationType _AsyncInfo) : _M_asyncInfo(_AsyncInfo) {}
1004 
1005 public:
1006     virtual void Cancel() { _M_asyncInfo.Get()->Cancel(); }
1007     virtual void Close() { _M_asyncInfo.Get()->Close(); }
1008 
1009     virtual property Windows::Foundation::HResult ErrorCode
1010     {
1011         Windows::Foundation::HResult get() { return _M_asyncInfo.Get()->ErrorCode; }
1012     }
1013 
1014     virtual property UINT Id
1015     {
1016         UINT get() { return _M_asyncInfo.Get()->Id; }
1017     }
1018 
1019     virtual property Windows::Foundation::AsyncStatus Status
1020     {
1021         Windows::Foundation::AsyncStatus get() { return _M_asyncInfo.Get()->Status; }
1022     }
1023 
1024     virtual _Result GetResults() { throw std::runtime_error("derived class must implement"); }
1025 
1026     virtual property Windows::Foundation::AsyncOperationCompletedHandler<_Result> ^ Completed {
1027         Windows::Foundation::AsyncOperationCompletedHandler<_Result> ^ get() { return _M_CompletedHandler; }
1028 
1029             void set(Windows::Foundation::AsyncOperationCompletedHandler<_Result> ^ value)
1030         {
1031             _M_CompletedHandler = value;
1032             _M_asyncInfo.Get()->Completed =
1033                 ref new _CompletionHandlerType([&](_AsyncOperationType, Windows::Foundation::AsyncStatus status) {
1034                     _M_CompletedHandler->Invoke(this, status);
1035                 });
1036         }
1037     }
1038 };
1039 
1040 /// <summary>
1041 ///     Class _IAsyncOperationWithProgressToAsyncOperationConverter is used to convert an instance of
1042 ///     IAsyncOperationWithProgress<T> into IAsyncOperation<T>
1043 /// </summary>
1044 template<typename _Result, typename _Progress>
1045 ref struct _IAsyncOperationWithProgressToAsyncOperationConverter sealed
1046     : _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress> ^
1047                      , Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result, _Progress>, _Result>
1048 {
1049     internal : _IAsyncOperationWithProgressToAsyncOperationConverter(
1050                    Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress> ^ _Operation)
1051         : _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress> ^,
1052                          Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result, _Progress>,
1053                          _Result>(_Operation)
1054     {
1055     }
1056 
1057 public:
1058     virtual _Result GetResults() override { return _M_asyncInfo.Get()->GetResults(); }
1059 };
1060 
1061 /// <summary>
1062 ///     Class _IAsyncActionToAsyncOperationConverter is used to convert an instance of IAsyncAction into
1063 ///     IAsyncOperation<_Unit_type>
1064 /// </summary>
1065 ref struct _IAsyncActionToAsyncOperationConverter sealed
1066     : _AsyncInfoImpl<Windows::Foundation::IAsyncAction ^
1067                      , Windows::Foundation::AsyncActionCompletedHandler, details::_Unit_type>
1068 {
1069     internal : _IAsyncActionToAsyncOperationConverter(Windows::Foundation::IAsyncAction ^ _Operation)
1070         : _AsyncInfoImpl<Windows::Foundation::IAsyncAction ^
1071                          , Windows::Foundation::AsyncActionCompletedHandler, details::_Unit_type>(_Operation)
1072     {
1073     }
1074 
1075 public:
1076     virtual details::_Unit_type GetResults() override
1077     {
1078         // Invoke GetResults on the IAsyncAction to allow exceptions to be thrown to higher layers before returning a
1079         // dummy value.
1080         _M_asyncInfo.Get()->GetResults();
1081         return details::_Unit_type();
1082     }
1083 };
1084 
1085 /// <summary>
1086 ///     Class _IAsyncActionWithProgressToAsyncOperationConverter is used to convert an instance of
1087 ///     IAsyncActionWithProgress into IAsyncOperation<_Unit_type>
1088 /// </summary>
1089 template<typename _Progress>
1090 ref struct _IAsyncActionWithProgressToAsyncOperationConverter sealed
1091     : _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress> ^
1092                      , Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>, details::_Unit_type>
1093 {
1094     internal
1095         : _IAsyncActionWithProgressToAsyncOperationConverter(Windows::Foundation::IAsyncActionWithProgress<_Progress> ^
1096                                                              _Action)
1097         : _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress> ^,
1098                          Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>,
1099                          details::_Unit_type>(_Action)
1100     {
1101     }
1102 
1103 public:
1104     virtual details::_Unit_type GetResults() override
1105     {
1106         // Invoke GetResults on the IAsyncActionWithProgress to allow exceptions to be thrown before returning a dummy
1107         // value.
1108         _M_asyncInfo.Get()->GetResults();
1109         return details::_Unit_type();
1110     }
1111 };
1112 #endif /* defined (__cplusplus_winrt) */
1113 } // namespace details
1114 
1115 /// <summary>
1116 ///     The <c>task_continuation_context</c> class allows you to specify where you would like a continuation to be
1117 ///     executed. It is only useful to use this class from a Windows Store app. For non-Windows Store apps, the task
1118 ///     continuation's execution context is determined by the runtime, and not configurable.
1119 /// </summary>
1120 /// <seealso cref="task Class"/>
1121 /**/
1122 class task_continuation_context : public details::_ContextCallback
1123 {
1124 public:
1125     /// <summary>
1126     ///     Creates the default task continuation context.
1127     /// </summary>
1128     /// <returns>
1129     ///     The default continuation context.
1130     /// </returns>
1131     /// <remarks>
1132     ///     The default context is used if you don't specify a continuation context when you call the <c>then</c>
1133     ///     method. In Windows applications for Windows 7 and below, as well as desktop applications on Windows 8 and
1134     ///     higher, the runtime determines where task continuations will execute. However, in a Windows Store app, the
1135     ///     default continuation context for a continuation on an apartment aware task is the apartment where
1136     ///     <c>then</c> is invoked. <para>An apartment aware task is a task that unwraps a Windows Runtime
1137     ///     <c>IAsyncInfo</c> interface, or a task that is descended from such a task. Therefore, if you schedule a
1138     ///     continuation on an apartment aware task in a Windows Runtime STA, the continuation will execute in that
1139     ///     STA.</para> <para>A continuation on a non-apartment aware task will execute in a context the Runtime
1140     ///     chooses.</para>
1141     /// </remarks>
1142     /**/
1143     static task_continuation_context use_default()
1144     {
1145 #if defined(__cplusplus_winrt)
1146         // The callback context is created with the context set to CaptureDeferred and resolved when it is used in
1147         // .then()
1148         return task_continuation_context(
1149             true); // sets it to deferred, is resolved in the constructor of _ContinuationTaskHandle
1150 #else  /* defined (__cplusplus_winrt) */
1151         return task_continuation_context();
1152 #endif /* defined (__cplusplus_winrt) */
1153     }
1154 
1155 #if defined(__cplusplus_winrt)
1156     /// <summary>
1157     ///     Creates a task continuation context which allows the Runtime to choose the execution context for a
1158     ///     continuation.
1159     /// </summary>
1160     /// <returns>
1161     ///     A task continuation context that represents an arbitrary location.
1162     /// </returns>
1163     /// <remarks>
1164     ///     When this continuation context is used the continuation will execute in a context the runtime chooses even
1165     ///     if the antecedent task is apartment aware. <para><c>use_arbitrary</c> can be used to turn off the default
1166     ///     behavior for a continuation on an apartment aware task created in an STA. </para> <para>This method is only
1167     ///     available to Windows Store apps.</para>
1168     /// </remarks>
1169     /**/
1170     static task_continuation_context use_arbitrary()
1171     {
1172         task_continuation_context _Arbitrary(true);
1173         _Arbitrary._Resolve(false);
1174         return _Arbitrary;
1175     }
1176 
1177     /// <summary>
1178     ///     Returns a task continuation context object that represents the current execution context.
1179     /// </summary>
1180     /// <returns>
1181     ///     The current execution context.
1182     /// </returns>
1183     /// <remarks>
1184     ///     This method captures the caller's Windows Runtime context so that continuations can be executed in the right
1185     ///     apartment. <para>The value returned by <c>use_current</c> can be used to indicate to the Runtime that the
1186     ///     continuation should execute in the captured context (STA vs MTA) regardless of whether or not the antecedent
1187     ///     task is apartment aware. An apartment aware task is a task that unwraps a Windows Runtime <c>IAsyncInfo</c>
1188     ///     interface, or a task that is descended from such a task. </para> <para>This method is only available to
1189     ///     Windows Store apps.</para>
1190     /// </remarks>
1191     /**/
1192     static task_continuation_context use_current()
1193     {
1194         task_continuation_context _Current(true);
1195         _Current._Resolve(true);
1196         return _Current;
1197     }
1198 #endif /* defined (__cplusplus_winrt) */
1199 
1200 private:
1201     task_continuation_context(bool _DeferCapture = false) : details::_ContextCallback(_DeferCapture) {}
1202 };
1203 
1204 class task_options;
1205 namespace details
1206 {
1207 struct _Internal_task_options
1208 {
1209     bool _M_hasPresetCreationCallstack;
1210     _TaskCreationCallstack _M_presetCreationCallstack;
1211 
1212     void _set_creation_callstack(const _TaskCreationCallstack& _callstack)
1213     {
1214         _M_hasPresetCreationCallstack = true;
1215         _M_presetCreationCallstack = _callstack;
1216     }
1217     _Internal_task_options() { _M_hasPresetCreationCallstack = false; }
1218 };
1219 
1220 inline _Internal_task_options& _get_internal_task_options(task_options& options);
1221 inline const _Internal_task_options& _get_internal_task_options(const task_options& options);
1222 } // namespace details
1223 /// <summary>
1224 ///     Represents the allowed options for creating a task
1225 /// </summary>
1226 class task_options
1227 {
1228 public:
1229     /// <summary>
1230     ///     Default list of task creation options
1231     /// </summary>
1232     task_options()
1233         : _M_Scheduler(get_ambient_scheduler())
1234         , _M_CancellationToken(cancellation_token::none())
1235         , _M_ContinuationContext(task_continuation_context::use_default())
1236         , _M_HasCancellationToken(false)
1237         , _M_HasScheduler(false)
1238     {
1239     }
1240 
1241     /// <summary>
1242     ///     Task option that specify a cancellation token
1243     /// </summary>
1244     task_options(cancellation_token _Token)
1245         : _M_Scheduler(get_ambient_scheduler())
1246         , _M_CancellationToken(_Token)
1247         , _M_ContinuationContext(task_continuation_context::use_default())
1248         , _M_HasCancellationToken(true)
1249         , _M_HasScheduler(false)
1250     {
1251     }
1252 
1253     /// <summary>
1254     ///     Task option that specify a continuation context. This is valid only for continuations (then)
1255     /// </summary>
1256     task_options(task_continuation_context _ContinuationContext)
1257         : _M_Scheduler(get_ambient_scheduler())
1258         , _M_CancellationToken(cancellation_token::none())
1259         , _M_ContinuationContext(_ContinuationContext)
1260         , _M_HasCancellationToken(false)
1261         , _M_HasScheduler(false)
1262     {
1263     }
1264 
1265     /// <summary>
1266     ///     Task option that specify a cancellation token and a continuation context. This is valid only for
1267     ///     continuations (then)
1268     /// </summary>
1269     task_options(cancellation_token _Token, task_continuation_context _ContinuationContext)
1270         : _M_Scheduler(get_ambient_scheduler())
1271         , _M_CancellationToken(_Token)
1272         , _M_ContinuationContext(_ContinuationContext)
1273         , _M_HasCancellationToken(false)
1274         , _M_HasScheduler(false)
1275     {
1276     }
1277 
1278     /// <summary>
1279     ///     Task option that specify a scheduler with shared lifetime
1280     /// </summary>
1281     template<typename _SchedType>
1282     task_options(std::shared_ptr<_SchedType> _Scheduler)
1283         : _M_Scheduler(std::move(_Scheduler))
1284         , _M_CancellationToken(cancellation_token::none())
1285         , _M_ContinuationContext(task_continuation_context::use_default())
1286         , _M_HasCancellationToken(false)
1287         , _M_HasScheduler(true)
1288     {
1289     }
1290 
1291     /// <summary>
1292     ///     Task option that specify a scheduler reference
1293     /// </summary>
1294     task_options(scheduler_interface& _Scheduler)
1295         : _M_Scheduler(&_Scheduler)
1296         , _M_CancellationToken(cancellation_token::none())
1297         , _M_ContinuationContext(task_continuation_context::use_default())
1298         , _M_HasCancellationToken(false)
1299         , _M_HasScheduler(true)
1300     {
1301     }
1302 
1303     /// <summary>
1304     ///     Task option that specify a scheduler
1305     /// </summary>
1306     task_options(scheduler_ptr _Scheduler)
1307         : _M_Scheduler(std::move(_Scheduler))
1308         , _M_CancellationToken(cancellation_token::none())
1309         , _M_ContinuationContext(task_continuation_context::use_default())
1310         , _M_HasCancellationToken(false)
1311         , _M_HasScheduler(true)
1312     {
1313     }
1314 
1315     /// <summary>
1316     ///     Task option copy constructor
1317     /// </summary>
1318     task_options(const task_options& _TaskOptions)
1319         : _M_Scheduler(_TaskOptions.get_scheduler())
1320         , _M_CancellationToken(_TaskOptions.get_cancellation_token())
1321         , _M_ContinuationContext(_TaskOptions.get_continuation_context())
1322         , _M_HasCancellationToken(_TaskOptions.has_cancellation_token())
1323         , _M_HasScheduler(_TaskOptions.has_scheduler())
1324     {
1325     }
1326 
1327     /// <summary>
1328     ///     Sets the given token in the options
1329     /// </summary>
1330     void set_cancellation_token(cancellation_token _Token)
1331     {
1332         _M_CancellationToken = _Token;
1333         _M_HasCancellationToken = true;
1334     }
1335 
1336     /// <summary>
1337     ///     Sets the given continuation context in the options
1338     /// </summary>
1339     void set_continuation_context(task_continuation_context _ContinuationContext)
1340     {
1341         _M_ContinuationContext = _ContinuationContext;
1342     }
1343 
1344     /// <summary>
1345     ///     Indicates whether a cancellation token was specified by the user
1346     /// </summary>
1347     bool has_cancellation_token() const { return _M_HasCancellationToken; }
1348 
1349     /// <summary>
1350     ///     Returns the cancellation token
1351     /// </summary>
1352     cancellation_token get_cancellation_token() const { return _M_CancellationToken; }
1353 
1354     /// <summary>
1355     ///     Returns the continuation context
1356     /// </summary>
1357     task_continuation_context get_continuation_context() const { return _M_ContinuationContext; }
1358 
1359     /// <summary>
1360     ///     Indicates whether a scheduler n was specified by the user
1361     /// </summary>
1362     bool has_scheduler() const { return _M_HasScheduler; }
1363 
1364     /// <summary>
1365     ///     Returns the scheduler
1366     /// </summary>
1367     scheduler_ptr get_scheduler() const { return _M_Scheduler; }
1368 
1369 private:
1370     task_options const& operator=(task_options const& _Right);
1371     friend details::_Internal_task_options& details::_get_internal_task_options(task_options&);
1372     friend const details::_Internal_task_options& details::_get_internal_task_options(const task_options&);
1373 
1374     scheduler_ptr _M_Scheduler;
1375     cancellation_token _M_CancellationToken;
1376     task_continuation_context _M_ContinuationContext;
1377     details::_Internal_task_options _M_InternalTaskOptions;
1378     bool _M_HasCancellationToken;
1379     bool _M_HasScheduler;
1380 };
1381 
1382 namespace details
1383 {
1384 inline _Internal_task_options& _get_internal_task_options(task_options& options)
1385 {
1386     return options._M_InternalTaskOptions;
1387 }
1388 inline const _Internal_task_options& _get_internal_task_options(const task_options& options)
1389 {
1390     return options._M_InternalTaskOptions;
1391 }
1392 
1393 struct _Task_impl_base;
1394 template<typename _ReturnType>
1395 struct _Task_impl;
1396 
1397 template<typename _ReturnType>
1398 struct _Task_ptr
1399 {
1400     typedef std::shared_ptr<_Task_impl<_ReturnType>> _Type;
1401     static _Type _Make(_CancellationTokenState* _Ct, scheduler_ptr _Scheduler_arg)
1402     {
1403         return std::make_shared<_Task_impl<_ReturnType>>(_Ct, _Scheduler_arg);
1404     }
1405 };
1406 
1407 typedef _TaskCollection_t::_TaskProcHandle_t _UnrealizedChore_t;
1408 typedef std::shared_ptr<_Task_impl_base> _Task_ptr_base;
1409 
1410 // The weak-typed base task handler for continuation tasks.
1411 struct _ContinuationTaskHandleBase : _UnrealizedChore_t
1412 {
1413     _ContinuationTaskHandleBase* _M_next;
1414     task_continuation_context _M_continuationContext;
1415     bool _M_isTaskBasedContinuation;
1416 
1417     // This field gives inlining scheduling policy for current chore.
1418     _TaskInliningMode_t _M_inliningMode;
1419 
1420     virtual _Task_ptr_base _GetTaskImplBase() const = 0;
1421 
1422     _ContinuationTaskHandleBase()
1423         : _M_next(nullptr)
1424         , _M_continuationContext(task_continuation_context::use_default())
1425         , _M_isTaskBasedContinuation(false)
1426         , _M_inliningMode(details::_NoInline)
1427     {
1428     }
1429 
1430     virtual ~_ContinuationTaskHandleBase() {}
1431 };
1432 
1433 #if PPLX_TASK_ASYNC_LOGGING
1434 // GUID used for identifying causality logs from PPLTask
1435 const ::Platform::Guid _PPLTaskCausalityPlatformID(
1436     0x7A76B220, 0xA758, 0x4E6E, 0xB0, 0xE0, 0xD7, 0xC6, 0xD7, 0x4A, 0x88, 0xFE);
1437 
1438 __declspec(selectany) volatile long _isCausalitySupported = 0;
1439 
1440 inline bool _IsCausalitySupported()
1441 {
1442 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
1443     if (_isCausalitySupported == 0)
1444     {
1445         long _causality = 1;
1446         OSVERSIONINFOEX _osvi = {};
1447         _osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1448 
1449         // The Causality is supported on Windows version higher than Windows 8
1450         _osvi.dwMajorVersion = 6;
1451         _osvi.dwMinorVersion = 3;
1452 
1453         DWORDLONG _conditionMask = 0;
1454         VER_SET_CONDITION(_conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
1455         VER_SET_CONDITION(_conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
1456 
1457         if (::VerifyVersionInfo(&_osvi, VER_MAJORVERSION | VER_MINORVERSION, _conditionMask))
1458         {
1459             _causality = 2;
1460         }
1461 
1462         _isCausalitySupported = _causality;
1463         return _causality == 2;
1464     }
1465 
1466     return _isCausalitySupported == 2 ? true : false;
1467 #else
1468     return true;
1469 #endif
1470 }
1471 
1472 // Stateful logger rests inside task_impl_base.
1473 struct _TaskEventLogger
1474 {
1475     _Task_impl_base* _M_task;
1476     bool _M_scheduled;
1477     bool _M_taskPostEventStarted;
1478 
1479     // Log before scheduling task
1480     void _LogScheduleTask(bool _isContinuation)
1481     {
1482         if (details::_IsCausalitySupported())
1483         {
1484             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCreation(
1485                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
1486                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1487                 _PPLTaskCausalityPlatformID,
1488                 reinterpret_cast<unsigned long long>(_M_task),
1489                 _isContinuation ? "pplx::PPLTask::ScheduleContinuationTask" : "pplx::PPLTask::ScheduleTask",
1490                 0);
1491             _M_scheduled = true;
1492         }
1493     }
1494 
1495     // It will log the cancel event but not canceled state. _LogTaskCompleted will log the terminal state, which
1496     // includes cancel state.
1497     void _LogCancelTask()
1498     {
1499         if (details::_IsCausalitySupported())
1500         {
1501             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationRelation(
1502                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Important,
1503                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1504                 _PPLTaskCausalityPlatformID,
1505                 reinterpret_cast<unsigned long long>(_M_task),
1506                 ::Windows::Foundation::Diagnostics::CausalityRelation::Cancel);
1507         }
1508     }
1509 
1510     // Log when task reaches terminal state. Note: the task can reach a terminal state (by cancellation or exception)
1511     // without having run
1512     void _LogTaskCompleted();
1513 
1514     // Log when task body (which includes user lambda and other scheduling code) begin to run
1515     void _LogTaskExecutionStarted() {}
1516 
1517     // Log when task body finish executing
1518     void _LogTaskExecutionCompleted()
1519     {
1520         if (_M_taskPostEventStarted && details::_IsCausalitySupported())
1521         {
1522             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(
1523                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
1524                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1525                 ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
1526         }
1527     }
1528 
1529     // Log right before user lambda being invoked
1530     void _LogWorkItemStarted()
1531     {
1532         if (details::_IsCausalitySupported())
1533         {
1534             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(
1535                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
1536                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1537                 _PPLTaskCausalityPlatformID,
1538                 reinterpret_cast<unsigned long long>(_M_task),
1539                 ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
1540         }
1541     }
1542 
1543     // Log right after user lambda being invoked
1544     void _LogWorkItemCompleted()
1545     {
1546         if (details::_IsCausalitySupported())
1547         {
1548             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(
1549                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
1550                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1551                 ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
1552 
1553             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(
1554                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
1555                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1556                 _PPLTaskCausalityPlatformID,
1557                 reinterpret_cast<unsigned long long>(_M_task),
1558                 ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
1559             _M_taskPostEventStarted = true;
1560         }
1561     }
1562 
1563     _TaskEventLogger(_Task_impl_base* _task) : _M_task(_task)
1564     {
1565         _M_scheduled = false;
1566         _M_taskPostEventStarted = false;
1567     }
1568 };
1569 
1570 // Exception safe logger for user lambda
1571 struct _TaskWorkItemRAIILogger
1572 {
1573     _TaskEventLogger& _M_logger;
1574     _TaskWorkItemRAIILogger(_TaskEventLogger& _taskHandleLogger) : _M_logger(_taskHandleLogger)
1575     {
1576         _M_logger._LogWorkItemStarted();
1577     }
1578 
1579     ~_TaskWorkItemRAIILogger() { _M_logger._LogWorkItemCompleted(); }
1580     _TaskWorkItemRAIILogger& operator=(const _TaskWorkItemRAIILogger&); // cannot be assigned
1581 };
1582 
1583 #else
1584 inline void _LogCancelTask(_Task_impl_base*) {}
1585 struct _TaskEventLogger
1586 {
1587     void _LogScheduleTask(bool) {}
1588     void _LogCancelTask() {}
1589     void _LogWorkItemStarted() {}
1590     void _LogWorkItemCompleted() {}
1591     void _LogTaskExecutionStarted() {}
1592     void _LogTaskExecutionCompleted() {}
1593     void _LogTaskCompleted() {}
1594     _TaskEventLogger(_Task_impl_base*) {}
1595 };
1596 struct _TaskWorkItemRAIILogger
1597 {
1598     _TaskWorkItemRAIILogger(_TaskEventLogger&) {}
1599 };
1600 #endif
1601 
1602 /// <summary>
1603 ///     The _PPLTaskHandle is the strong-typed task handle base. All user task functions need to be wrapped in this task
1604 ///     handler to be executable by PPL. By deriving from a different _BaseTaskHandle, it can be used for both initial
1605 ///     tasks and continuation tasks. For initial tasks, _PPLTaskHandle will be derived from _UnrealizedChore_t, and for
1606 ///     continuation tasks, it will be derived from _ContinuationTaskHandleBase. The life time of the _PPLTaskHandle
1607 ///     object is be managed by runtime if task handle is scheduled.
1608 /// </summary>
1609 /// <typeparam name="_ReturnType">
1610 ///     The result type of the _Task_impl.
1611 /// </typeparam>
1612 /// <typeparam name="_DerivedTaskHandle">
1613 ///     The derived task handle class. The <c>operator ()</c> needs to be implemented.
1614 /// </typeparam>
1615 /// <typeparam name="_BaseTaskHandle">
1616 ///     The base class from which _PPLTaskHandle should be derived. This is either _UnrealizedChore_t or
1617 ///     _ContinuationTaskHandleBase.
1618 /// </typeparam>
1619 template<typename _ReturnType, typename _DerivedTaskHandle, typename _BaseTaskHandle>
1620 struct _PPLTaskHandle : _BaseTaskHandle
1621 {
1622     _PPLTaskHandle(const typename _Task_ptr<_ReturnType>::_Type& _PTask) : _M_pTask(_PTask) {}
1623 
1624     virtual ~_PPLTaskHandle()
1625     {
1626         // Here is the sink of all task completion code paths
1627         _M_pTask->_M_taskEventLogger._LogTaskCompleted();
1628     }
1629 
1630     virtual void invoke() const
1631     {
1632         // All exceptions should be rethrown to finish cleanup of the task collection. They will be caught and handled
1633         // by the runtime.
1634         _ASSERTE((bool)_M_pTask);
1635         if (!_M_pTask->_TransitionedToStarted())
1636         {
1637             static_cast<const _DerivedTaskHandle*>(this)->_SyncCancelAndPropagateException();
1638             return;
1639         }
1640 
1641         _M_pTask->_M_taskEventLogger._LogTaskExecutionStarted();
1642         try
1643         {
1644             // All derived task handle must implement this contract function.
1645             static_cast<const _DerivedTaskHandle*>(this)->_Perform();
1646         }
1647         catch (const task_canceled&)
1648         {
1649             _M_pTask->_Cancel(true);
1650         }
1651         catch (const _Interruption_exception&)
1652         {
1653             _M_pTask->_Cancel(true);
1654         }
1655 #if defined(__cplusplus_winrt)
1656         catch (::Platform::Exception ^ _E)
1657         {
1658             _M_pTask->_CancelWithException(_E);
1659         }
1660 #endif /* defined (__cplusplus_winrt) */
1661         catch (...)
1662         {
1663             _M_pTask->_CancelWithException(std::current_exception());
1664         }
1665         _M_pTask->_M_taskEventLogger._LogTaskExecutionCompleted();
1666     }
1667 
1668     // Cast _M_pTask pointer to "type-less" _Task_impl_base pointer, which can be used in _ContinuationTaskHandleBase.
1669     // The return value should be automatically optimized by R-value ref.
1670     _Task_ptr_base _GetTaskImplBase() const { return _M_pTask; }
1671 
1672     typename _Task_ptr<_ReturnType>::_Type _M_pTask;
1673 
1674 private:
1675     _PPLTaskHandle const& operator=(_PPLTaskHandle const&); // no assignment operator
1676 };
1677 
1678 /// <summary>
1679 ///     The base implementation of a first-class task. This class contains all the non-type specific
1680 ///     implementation details of the task.
1681 /// </summary>
1682 /**/
1683 struct _Task_impl_base
1684 {
1685     enum _TaskInternalState
1686     {
1687         // Tracks the state of the task, rather than the task collection on which the task is scheduled
1688         _Created,
1689         _Started,
1690         _PendingCancel,
1691         _Completed,
1692         _Canceled
1693     };
1694 // _M_taskEventLogger - 'this' : used in base member initializer list
1695 #if defined(_MSC_VER)
1696 #pragma warning(push)
1697 #pragma warning(disable : 4355)
1698 #endif
1699     _Task_impl_base(_CancellationTokenState* _PTokenState, scheduler_ptr _Scheduler_arg)
1700         : _M_TaskState(_Created)
1701         , _M_fFromAsync(false)
1702         , _M_fUnwrappedTask(false)
1703         , _M_pRegistration(nullptr)
1704         , _M_Continuations(nullptr)
1705         , _M_TaskCollection(_Scheduler_arg)
1706         , _M_taskEventLogger(this)
1707     {
1708         // Set cancellation token
1709         _M_pTokenState = _PTokenState;
1710         _ASSERTE(_M_pTokenState != nullptr);
1711         if (_M_pTokenState != _CancellationTokenState::_None()) _M_pTokenState->_Reference();
1712     }
1713 #if defined(_MSC_VER)
1714 #pragma warning(pop)
1715 #endif
1716 
1717     virtual ~_Task_impl_base()
1718     {
1719         _ASSERTE(_M_pTokenState != nullptr);
1720         if (_M_pTokenState != _CancellationTokenState::_None())
1721         {
1722             _M_pTokenState->_Release();
1723         }
1724     }
1725 
1726     task_status _Wait()
1727     {
1728         bool _DoWait = true;
1729 
1730 #if defined(__cplusplus_winrt)
1731         if (_IsNonBlockingThread())
1732         {
1733             // In order to prevent Windows Runtime STA threads from blocking the UI, calling task.wait() task.get() is
1734             // illegal if task has not been completed.
1735             if (!_IsCompleted() && !_IsCanceled())
1736             {
1737                 throw invalid_operation("Illegal to wait on a task in a Windows Runtime STA");
1738             }
1739             else
1740             {
1741                 // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestors's task
1742                 // group. If a continuation needs to be marshaled to a different apartment, instead of scheduling, we
1743                 // make a synchronous cross apartment COM call to execute the continuation. If it then happens to do
1744                 // something which waits on the ancestor (say it calls .get(), which task based continuations are wont
1745                 // to do), waiting on the task group results in on the chore that is making this synchronous callback,
1746                 // which causes a deadlock. To avoid this, we test the state ancestor's event , and we will NOT wait on
1747                 // if it has finished execution (which means now we are on the inline synchronous callback).
1748                 _DoWait = false;
1749             }
1750         }
1751 #endif /* defined (__cplusplus_winrt) */
1752         if (_DoWait)
1753         {
1754             // If this task was created from a Windows Runtime async operation, do not attempt to inline it. The
1755             // async operation will take place on a thread in the appropriate apartment Simply wait for the completed
1756             // event to be set.
1757             if (_M_fFromAsync)
1758             {
1759                 _M_TaskCollection._Wait();
1760             }
1761             else
1762             {
1763                 // Wait on the task collection to complete. The task collection is guaranteed to still be
1764                 // valid since the task must be still within scope so that the _Task_impl_base destructor
1765                 // has not yet been called. This call to _Wait potentially inlines execution of work.
1766                 try
1767                 {
1768                     // Invoking wait on a task collection resets the state of the task collection. This means that
1769                     // if the task collection itself were canceled, or had encountered an exception, only the first
1770                     // call to wait will receive this status. However, both cancellation and exceptions flowing through
1771                     // tasks set state in the task impl itself.
1772 
1773                     // When it returns canceled, either work chore or the cancel thread should already have set task's
1774                     // state properly -- canceled state or completed state (because there was no interruption point).
1775                     // For tasks with unwrapped tasks, we should not change the state of current task, since the
1776                     // unwrapped task are still running.
1777                     _M_TaskCollection._RunAndWait();
1778                 }
1779                 catch (details::_Interruption_exception&)
1780                 {
1781                     // The _TaskCollection will never be an interruption point since it has a none token.
1782                     _ASSERTE(false);
1783                 }
1784                 catch (task_canceled&)
1785                 {
1786                     // task_canceled is a special exception thrown by cancel_current_task. The spec states that
1787                     // cancel_current_task must be called from code that is executed within the task (throwing it from
1788                     // parallel work created by and waited upon by the task is acceptable). We can safely assume that
1789                     // the task wrapper _PPLTaskHandle::operator() has seen the exception and canceled the task. Swallow
1790                     // the exception here.
1791                     _ASSERTE(_IsCanceled());
1792                 }
1793 #if defined(__cplusplus_winrt)
1794                 catch (::Platform::Exception ^ _E)
1795                 {
1796                     // Its possible the task body hasn't seen the exception, if so we need to cancel with exception
1797                     // here.
1798                     if (!_HasUserException())
1799                     {
1800                         _CancelWithException(_E);
1801                     }
1802                     // Rethrow will mark the exception as observed.
1803                     _M_exceptionHolder->_RethrowUserException();
1804                 }
1805 #endif /* defined (__cplusplus_winrt) */
1806                 catch (...)
1807                 {
1808                     // Its possible the task body hasn't seen the exception, if so we need to cancel with exception
1809                     // here.
1810                     if (!_HasUserException())
1811                     {
1812                         _CancelWithException(std::current_exception());
1813                     }
1814                     // Rethrow will mark the exception as observed.
1815                     _M_exceptionHolder->_RethrowUserException();
1816                 }
1817 
1818                 // If the lambda body for this task (executed or waited upon in _RunAndWait above) happened to return a
1819                 // task which is to be unwrapped and plumbed to the output of this task, we must not only wait on the
1820                 // lambda body, we must wait on the **INNER** body. It is in theory possible that we could inline such
1821                 // if we plumb a series of things through; however, this takes the tact of simply waiting upon the
1822                 // completion signal.
1823                 if (_M_fUnwrappedTask)
1824                 {
1825                     _M_TaskCollection._Wait();
1826                 }
1827             }
1828         }
1829 
1830         if (_HasUserException())
1831         {
1832             _M_exceptionHolder->_RethrowUserException();
1833         }
1834         else if (_IsCanceled())
1835         {
1836             return canceled;
1837         }
1838         _ASSERTE(_IsCompleted());
1839         return completed;
1840     }
1841 
1842     /// <summary>
1843     ///     Requests cancellation on the task and schedules continuations if the task can be transitioned to a terminal
1844     ///     state.
1845     /// </summary>
1846     /// <param name="_SynchronousCancel">
1847     ///     Set to true if the cancel takes place as a result of the task body encountering an exception, or because an
1848     ///     ancestor or task_completion_event the task was registered with were canceled with an exception. A
1849     ///     synchronous cancel is one that assures the task could not be running on a different thread at the time the
1850     ///     cancellation is in progress. An asynchronous cancel is one where the thread performing the cancel has no
1851     ///     control over the thread that could be executing the task, that is the task could execute concurrently while
1852     ///     the cancellation is in progress.
1853     /// </param>
1854     /// <param name="_UserException">
1855     ///     Whether an exception other than the internal runtime cancellation exceptions caused this cancellation.
1856     /// </param>
1857     /// <param name="_PropagatedFromAncestor">
1858     ///     Whether this exception came from an ancestor task or a task_completion_event as opposed to an exception that
1859     ///     was encountered by the task itself. Only valid when _UserException is set to true.
1860     /// </param>
1861     /// <param name="_ExHolder">
1862     ///     The exception holder that represents the exception. Only valid when _UserException is set to true.
1863     /// </param>
1864     virtual bool _CancelAndRunContinuations(bool _SynchronousCancel,
1865                                             bool _UserException,
1866                                             bool _PropagatedFromAncestor,
1867                                             const std::shared_ptr<_ExceptionHolder>& _ExHolder) = 0;
1868 
1869     bool _Cancel(bool _SynchronousCancel)
1870     {
1871         // Send in a dummy value for exception. It is not used when the first parameter is false.
1872         return _CancelAndRunContinuations(_SynchronousCancel, false, false, _M_exceptionHolder);
1873     }
1874 
1875     bool _CancelWithExceptionHolder(const std::shared_ptr<_ExceptionHolder>& _ExHolder, bool _PropagatedFromAncestor)
1876     {
1877         // This task was canceled because an ancestor task encountered an exception.
1878         return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder);
1879     }
1880 
1881 #if defined(__cplusplus_winrt)
1882     bool _CancelWithException(::Platform::Exception ^ _Exception)
1883     {
1884         // This task was canceled because the task body encountered an exception.
1885         _ASSERTE(!_HasUserException());
1886         return _CancelAndRunContinuations(
1887             true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1888     }
1889 #endif /* defined (__cplusplus_winrt) */
1890 
1891     bool _CancelWithException(const std::exception_ptr& _Exception)
1892     {
1893         // This task was canceled because the task body encountered an exception.
1894         _ASSERTE(!_HasUserException());
1895         return _CancelAndRunContinuations(
1896             true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1897     }
1898 
1899     void _RegisterCancellation(std::weak_ptr<_Task_impl_base> _WeakPtr)
1900     {
1901         _ASSERTE(details::_CancellationTokenState::_IsValid(_M_pTokenState));
1902 
1903         auto _CancellationCallback = [_WeakPtr]() {
1904             // Taking ownership of the task prevents dead lock during destruction
1905             // if the destructor waits for the cancellations to be finished
1906             auto _task = _WeakPtr.lock();
1907             if (_task != nullptr) _task->_Cancel(false);
1908         };
1909 
1910         _M_pRegistration =
1911             new details::_CancellationTokenCallback<decltype(_CancellationCallback)>(_CancellationCallback);
1912         _M_pTokenState->_RegisterCallback(_M_pRegistration);
1913     }
1914 
1915     void _DeregisterCancellation()
1916     {
1917         if (_M_pRegistration != nullptr)
1918         {
1919             _M_pTokenState->_DeregisterCallback(_M_pRegistration);
1920             _M_pRegistration->_Release();
1921             _M_pRegistration = nullptr;
1922         }
1923     }
1924 
1925     bool _IsCreated() { return (_M_TaskState == _Created); }
1926 
1927     bool _IsStarted() { return (_M_TaskState == _Started); }
1928 
1929     bool _IsPendingCancel() { return (_M_TaskState == _PendingCancel); }
1930 
1931     bool _IsCompleted() { return (_M_TaskState == _Completed); }
1932 
1933     bool _IsCanceled() { return (_M_TaskState == _Canceled); }
1934 
1935     bool _HasUserException() { return static_cast<bool>(_M_exceptionHolder); }
1936 
1937     const std::shared_ptr<_ExceptionHolder>& _GetExceptionHolder()
1938     {
1939         _ASSERTE(_HasUserException());
1940         return _M_exceptionHolder;
1941     }
1942 
1943     bool _IsApartmentAware() { return _M_fFromAsync; }
1944 
1945     void _SetAsync(bool _Async = true) { _M_fFromAsync = _Async; }
1946 
1947     _TaskCreationCallstack _GetTaskCreationCallstack() { return _M_pTaskCreationCallstack; }
1948 
1949     void _SetTaskCreationCallstack(const _TaskCreationCallstack& _Callstack) { _M_pTaskCreationCallstack = _Callstack; }
1950 
1951     /// <summary>
1952     ///     Helper function to schedule the task on the Task Collection.
1953     /// </summary>
1954     /// <param name="_PTaskHandle">
1955     ///     The task chore handle that need to be executed.
1956     /// </param>
1957     /// <param name="_InliningMode">
1958     ///     The inlining scheduling policy for current _PTaskHandle.
1959     /// </param>
1960     void _ScheduleTask(_UnrealizedChore_t* _PTaskHandle, _TaskInliningMode_t _InliningMode)
1961     {
1962         try
1963         {
1964             _M_TaskCollection._ScheduleTask(_PTaskHandle, _InliningMode);
1965         }
1966         catch (const task_canceled&)
1967         {
1968             // task_canceled is a special exception thrown by cancel_current_task. The spec states that
1969             // cancel_current_task must be called from code that is executed within the task (throwing it from parallel
1970             // work created by and waited upon by the task is acceptable). We can safely assume that the task wrapper
1971             // _PPLTaskHandle::operator() has seen the exception and canceled the task. Swallow the exception here.
1972             _ASSERTE(_IsCanceled());
1973         }
1974         catch (const _Interruption_exception&)
1975         {
1976             // The _TaskCollection will never be an interruption point since it has a none token.
1977             _ASSERTE(false);
1978         }
1979         catch (...)
1980         {
1981             // The exception could have come from two places:
1982             //   1. From the chore body, so it already should have been caught and canceled.
1983             //      In this case swallow the exception.
1984             //   2. From trying to actually schedule the task on the scheduler.
1985             //      In this case cancel the task with the current exception, otherwise the
1986             //      task will never be signaled leading to deadlock when waiting on the task.
1987             if (!_HasUserException())
1988             {
1989                 _CancelWithException(std::current_exception());
1990             }
1991         }
1992     }
1993 
1994     /// <summary>
1995     ///     Function executes a continuation. This function is recorded by a parent task implementation
1996     ///     when a continuation is created in order to execute later.
1997     /// </summary>
1998     /// <param name="_PTaskHandle">
1999     ///     The continuation task chore handle that need to be executed.
2000     /// </param>
2001     /**/
2002     void _RunContinuation(_ContinuationTaskHandleBase* _PTaskHandle)
2003     {
2004         _Task_ptr_base _ImplBase = _PTaskHandle->_GetTaskImplBase();
2005         if (_IsCanceled() && !_PTaskHandle->_M_isTaskBasedContinuation)
2006         {
2007             if (_HasUserException())
2008             {
2009                 // If the ancestor encountered an exception, transfer the exception to the continuation
2010                 // This traverses down the tree to propagate the exception.
2011                 _ImplBase->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
2012             }
2013             else
2014             {
2015                 // If the ancestor was canceled, then your own execution should be canceled.
2016                 // This traverses down the tree to cancel it.
2017                 _ImplBase->_Cancel(true);
2018             }
2019         }
2020         else
2021         {
2022             // This can only run when the ancestor has completed or it's a task based continuation that fires when a
2023             // task is canceled (with or without a user exception).
2024             _ASSERTE(_IsCompleted() || _PTaskHandle->_M_isTaskBasedContinuation);
2025             _ASSERTE(!_ImplBase->_IsCanceled());
2026             return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
2027         }
2028 
2029         // If the handle is not scheduled, we need to manually delete it.
2030         delete _PTaskHandle;
2031     }
2032 
2033     // Schedule a continuation to run
2034     void _ScheduleContinuationTask(_ContinuationTaskHandleBase* _PTaskHandle)
2035     {
2036         _M_taskEventLogger._LogScheduleTask(true);
2037         // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a
2038         // different Windows Runtime apartment)
2039         if (_PTaskHandle->_M_continuationContext._HasCapturedContext())
2040         {
2041             // For those continuations need to be scheduled inside captured context, we will try to apply automatic
2042             // inlining to their inline modes, if they haven't been specified as _ForceInline yet. This change will
2043             // encourage those continuations to be executed inline so that reduce the cost of marshaling. For normal
2044             // continuations we won't do any change here, and their inline policies are completely decided by ._ThenImpl
2045             // method.
2046             if (_PTaskHandle->_M_inliningMode != details::_ForceInline)
2047             {
2048                 _PTaskHandle->_M_inliningMode = details::_DefaultAutoInline;
2049             }
2050             _ScheduleFuncWithAutoInline(
2051                 [_PTaskHandle]() {
2052                     // Note that we cannot directly capture "this" pointer, instead, we should use _TaskImplPtr, a
2053                     // shared_ptr to the _Task_impl_base. Because "this" pointer will be invalid as soon as _PTaskHandle
2054                     // get deleted. _PTaskHandle will be deleted after being scheduled.
2055                     auto _TaskImplPtr = _PTaskHandle->_GetTaskImplBase();
2056                     if (details::_ContextCallback::_CaptureCurrent() == _PTaskHandle->_M_continuationContext)
2057                     {
2058                         _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
2059                     }
2060                     else
2061                     {
2062                         //
2063                         // It's entirely possible that the attempt to marshal the call into a differing context will
2064                         // fail. In this case, we need to handle the exception and mark the continuation as canceled
2065                         // with the appropriate exception. There is one slight hitch to this:
2066                         //
2067                         // NOTE: COM's legacy behavior is to swallow SEH exceptions and marshal them back as HRESULTS.
2068                         // This will in effect turn an SEH into a C++ exception that gets tagged on the task. One
2069                         // unfortunate result of this is that various pieces of the task infrastructure will not be in a
2070                         // valid state after this in /EHsc (due to the lack of destructors running, etc...).
2071                         //
2072                         try
2073                         {
2074                             // Dev10 compiler needs this!
2075                             auto _PTaskHandle1 = _PTaskHandle;
2076                             _PTaskHandle->_M_continuationContext._CallInContext([_PTaskHandle1, _TaskImplPtr]() {
2077                                 _TaskImplPtr->_ScheduleTask(_PTaskHandle1, details::_ForceInline);
2078                             });
2079                         }
2080 #if defined(__cplusplus_winrt)
2081                         catch (::Platform::Exception ^ _E)
2082                         {
2083                             _TaskImplPtr->_CancelWithException(_E);
2084                         }
2085 #endif /* defined (__cplusplus_winrt) */
2086                         catch (...)
2087                         {
2088                             _TaskImplPtr->_CancelWithException(std::current_exception());
2089                         }
2090                     }
2091                 },
2092                 _PTaskHandle->_M_inliningMode);
2093         }
2094         else
2095         {
2096             _ScheduleTask(_PTaskHandle, _PTaskHandle->_M_inliningMode);
2097         }
2098     }
2099 
2100     /// <summary>
2101     ///     Schedule the actual continuation. This will either schedule the function on the continuation task's
2102     ///     implementation if the task has completed or append it to a list of functions to execute when the task
2103     ///     actually does complete.
2104     /// </summary>
2105     /// <typeparam name="_FuncInputType">
2106     ///     The input type of the task.
2107     /// </typeparam>
2108     /// <typeparam name="_FuncOutputType">
2109     ///     The output type of the task.
2110     /// </typeparam>
2111     /**/
2112     void _ScheduleContinuation(_ContinuationTaskHandleBase* _PTaskHandle)
2113     {
2114         enum
2115         {
2116             _Nothing,
2117             _Schedule,
2118             _Cancel,
2119             _CancelWithException
2120         } _Do = _Nothing;
2121 
2122         // If the task has canceled, cancel the continuation. If the task has completed, execute the continuation right
2123         // away. Otherwise, add it to the list of pending continuations
2124         {
2125             ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2126             if (_IsCompleted() || (_IsCanceled() && _PTaskHandle->_M_isTaskBasedContinuation))
2127             {
2128                 _Do = _Schedule;
2129             }
2130             else if (_IsCanceled())
2131             {
2132                 if (_HasUserException())
2133                 {
2134                     _Do = _CancelWithException;
2135                 }
2136                 else
2137                 {
2138                     _Do = _Cancel;
2139                 }
2140             }
2141             else
2142             {
2143                 // chain itself on the continuation chain.
2144                 _PTaskHandle->_M_next = _M_Continuations;
2145                 _M_Continuations = _PTaskHandle;
2146             }
2147         }
2148 
2149         // Cancellation and execution of continuations should be performed after releasing the lock. Continuations off
2150         // of async tasks may execute inline.
2151         switch (_Do)
2152         {
2153             case _Schedule:
2154             {
2155                 _PTaskHandle->_GetTaskImplBase()->_ScheduleContinuationTask(_PTaskHandle);
2156                 break;
2157             }
2158             case _Cancel:
2159             {
2160                 // If the ancestor was canceled, then your own execution should be canceled.
2161                 // This traverses down the tree to cancel it.
2162                 _PTaskHandle->_GetTaskImplBase()->_Cancel(true);
2163 
2164                 delete _PTaskHandle;
2165                 break;
2166             }
2167             case _CancelWithException:
2168             {
2169                 // If the ancestor encountered an exception, transfer the exception to the continuation
2170                 // This traverses down the tree to propagate the exception.
2171                 _PTaskHandle->_GetTaskImplBase()->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
2172 
2173                 delete _PTaskHandle;
2174                 break;
2175             }
2176             case _Nothing:
2177             default:
2178                 // In this case, we have inserted continuation to continuation chain,
2179                 // nothing more need to be done, just leave.
2180                 break;
2181         }
2182     }
2183 
2184     void _RunTaskContinuations()
2185     {
2186         // The link list can no longer be modified at this point,
2187         // since all following up continuations will be scheduled by themselves.
2188         _ContinuationList _Cur = _M_Continuations, _Next;
2189         _M_Continuations = nullptr;
2190         while (_Cur)
2191         {
2192             // Current node might be deleted after running,
2193             // so we must fetch the next first.
2194             _Next = _Cur->_M_next;
2195             _RunContinuation(_Cur);
2196             _Cur = _Next;
2197         }
2198     }
2199 
2200 #if defined(__cplusplus_winrt)
2201     static bool _IsNonBlockingThread()
2202     {
2203         APTTYPE _AptType;
2204         APTTYPEQUALIFIER _AptTypeQualifier;
2205 
2206         HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
2207         //
2208         // If it failed, it's not a Windows Runtime/COM initialized thread. This is not a failure.
2209         //
2210         if (SUCCEEDED(hr))
2211         {
2212             switch (_AptType)
2213             {
2214                 case APTTYPE_STA:
2215                 case APTTYPE_MAINSTA: return true; break;
2216                 case APTTYPE_NA:
2217                     switch (_AptTypeQualifier)
2218                     {
2219                         // A thread executing in a neutral apartment is either STA or MTA. To find out if this thread is
2220                         // allowed to wait, we check the app qualifier. If it is an STA thread executing in a neutral
2221                         // apartment, waiting is illegal, because the thread is responsible for pumping messages and
2222                         // waiting on a task could take the thread out of circulation for a while.
2223                         case APTTYPEQUALIFIER_NA_ON_STA:
2224                         case APTTYPEQUALIFIER_NA_ON_MAINSTA: return true; break;
2225                     }
2226                     break;
2227             }
2228         }
2229 
2230 #if _UITHREADCTXT_SUPPORT
2231         // This method is used to throw an exception in _Wait() if called within STA.  We
2232         // want the same behavior if _Wait is called on the UI thread.
2233         if (SUCCEEDED(CaptureUiThreadContext(nullptr)))
2234         {
2235             return true;
2236         }
2237 #endif /* _UITHREADCTXT_SUPPORT */
2238 
2239         return false;
2240     }
2241 
2242     template<typename _ReturnType, typename>
2243     static void _AsyncInit(
2244         const typename _Task_ptr<_ReturnType>::_Type& _OuterTask,
2245         Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value> ^ _AsyncOp)
2246     {
2247         // This method is invoked either when a task is created from an existing async operation or
2248         // when a lambda that creates an async operation executes.
2249 
2250         // If the outer task is pending cancel, cancel the async operation before setting the completed handler. The COM
2251         // reference on the IAsyncInfo object will be released when all ^references to the operation go out of scope.
2252 
2253         // This assertion uses the existence of taskcollection to determine if the task was created from an event.
2254         // That is no longer valid as even tasks created from a user lambda could have no underlying taskcollection
2255         // when a custom scheduler is used.
2256         // _ASSERTE((!_OuterTask->_M_TaskCollection._IsCreated() || _OuterTask->_M_fUnwrappedTask) &&
2257         // !_OuterTask->_IsCanceled());
2258 
2259         // Pass the shared_ptr by value into the lambda instead of using 'this'.
2260         _AsyncOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType>(
2261             [_OuterTask](
2262                 Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value> ^
2263                     _Operation,
2264                 Windows::Foundation::AsyncStatus _Status) mutable {
2265                 if (_Status == Windows::Foundation::AsyncStatus::Canceled)
2266                 {
2267                     _OuterTask->_Cancel(true);
2268                 }
2269                 else if (_Status == Windows::Foundation::AsyncStatus::Error)
2270                 {
2271                     _OuterTask->_CancelWithException(
2272                         ::Platform::Exception::ReCreateException(static_cast<int>(_Operation->ErrorCode.Value)));
2273                 }
2274                 else
2275                 {
2276                     _ASSERTE(_Status == Windows::Foundation::AsyncStatus::Completed);
2277                     _OuterTask->_FinalizeAndRunContinuations(_Operation->GetResults());
2278                 }
2279 
2280                 // Take away this shared pointers reference on the task instead of waiting for the delegate to be
2281                 // released. It could be released on a different thread after a delay, and not releasing the reference
2282                 // here could cause the tasks to hold on to resources longer than they should. As an example, without
2283                 // this reset, writing to a file followed by reading from it using the Windows Runtime Async APIs causes
2284                 // a sharing violation. Using const_cast is the workaround for failed mutable keywords
2285                 const_cast<_Task_ptr<_ReturnType>::_Type&>(_OuterTask).reset();
2286             });
2287         _OuterTask->_SetUnwrappedAsyncOp(_AsyncOp);
2288     }
2289 #endif /* defined (__cplusplus_winrt) */
2290 
2291     template<typename _ReturnType, typename _InternalReturnType>
2292     static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type& _OuterTask,
2293                            const task<_InternalReturnType>& _UnwrappedTask)
2294     {
2295         _ASSERTE(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled());
2296 
2297         //
2298         // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in
2299         // the presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception
2300         // handling continuation off the inner task which does the appropriate funneling to the outer one. We use _Then
2301         // instead of then to prevent the exception from being marked as observed by our internal continuation. This
2302         // continuation must be scheduled regardless of whether or not the _OuterTask task is canceled.
2303         //
2304         _UnwrappedTask._Then(
2305             [_OuterTask](task<_InternalReturnType> _AncestorTask) {
2306                 if (_AncestorTask._GetImpl()->_IsCompleted())
2307                 {
2308                     _OuterTask->_FinalizeAndRunContinuations(_AncestorTask._GetImpl()->_GetResult());
2309                 }
2310                 else
2311                 {
2312                     _ASSERTE(_AncestorTask._GetImpl()->_IsCanceled());
2313                     if (_AncestorTask._GetImpl()->_HasUserException())
2314                     {
2315                         // Set _PropagatedFromAncestor to false, since _AncestorTask is not an ancestor of
2316                         // _UnwrappedTask. Instead, it is the enclosing task.
2317                         _OuterTask->_CancelWithExceptionHolder(_AncestorTask._GetImpl()->_GetExceptionHolder(), false);
2318                     }
2319                     else
2320                     {
2321                         _OuterTask->_Cancel(true);
2322                     }
2323                 }
2324             },
2325             nullptr,
2326             details::_DefaultAutoInline);
2327     }
2328 
2329     scheduler_ptr _GetScheduler() const { return _M_TaskCollection._GetScheduler(); }
2330 
2331     // Tracks the internal state of the task
2332     std::atomic<_TaskInternalState> _M_TaskState;
2333     // Set to true either if the ancestor task had the flag set to true, or if the lambda that does the work of this
2334     // task returns an async operation or async action that is unwrapped by the runtime.
2335     bool _M_fFromAsync;
2336     // Set to true when a continuation unwraps a task or async operation.
2337     bool _M_fUnwrappedTask;
2338 
2339     // An exception thrown by the task body is captured in an exception holder and it is shared with all value based
2340     // continuations rooted at the task. The exception is 'observed' if the user invokes get()/wait() on any of the
2341     // tasks that are sharing this exception holder. If the exception is not observed by the time the internal object
2342     // owned by the shared pointer destructs, the process will fail fast.
2343     std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2344 
2345     ::pplx::extensibility::critical_section_t _M_ContinuationsCritSec;
2346 
2347     // The cancellation token state.
2348     _CancellationTokenState* _M_pTokenState;
2349 
2350     // The registration on the token.
2351     _CancellationTokenRegistration* _M_pRegistration;
2352 
2353     typedef _ContinuationTaskHandleBase* _ContinuationList;
2354     _ContinuationList _M_Continuations;
2355 
2356     // The async task collection wrapper
2357     ::pplx::details::_TaskCollection_t _M_TaskCollection;
2358 
2359     // Callstack for function call (constructor or .then) that created this task impl.
2360     _TaskCreationCallstack _M_pTaskCreationCallstack;
2361 
2362     _TaskEventLogger _M_taskEventLogger;
2363 
2364 private:
2365     // Must not be copied by value:
2366     _Task_impl_base(const _Task_impl_base&);
2367     _Task_impl_base const& operator=(_Task_impl_base const&);
2368 };
2369 
2370 #if PPLX_TASK_ASYNC_LOGGING
2371 inline void _TaskEventLogger::_LogTaskCompleted()
2372 {
2373     if (_M_scheduled)
2374     {
2375         ::Windows::Foundation::AsyncStatus _State;
2376         if (_M_task->_IsCompleted())
2377             _State = ::Windows::Foundation::AsyncStatus::Completed;
2378         else if (_M_task->_HasUserException())
2379             _State = ::Windows::Foundation::AsyncStatus::Error;
2380         else
2381             _State = ::Windows::Foundation::AsyncStatus::Canceled;
2382 
2383         if (details::_IsCausalitySupported())
2384         {
2385             ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCompletion(
2386                 ::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required,
2387                 ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2388                 _PPLTaskCausalityPlatformID,
2389                 reinterpret_cast<unsigned long long>(_M_task),
2390                 _State);
2391         }
2392     }
2393 }
2394 #endif
2395 
2396 /// <summary>
2397 ///     The implementation of a first-class task. This structure contains the task group used to execute
2398 ///     the task function and handles the scheduling. The _Task_impl is created as a shared_ptr
2399 ///     member of the the public task class, so its destruction is handled automatically.
2400 /// </summary>
2401 /// <typeparam name="_ReturnType">
2402 ///     The result type of this task.
2403 /// </typeparam>
2404 /**/
2405 template<typename _ReturnType>
2406 struct _Task_impl : public _Task_impl_base
2407 {
2408 #if defined(__cplusplus_winrt)
2409     typedef Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>
2410         _AsyncOperationType;
2411 #endif // defined(__cplusplus_winrt)
2412     _Task_impl(_CancellationTokenState* _Ct, scheduler_ptr _Scheduler_arg) : _Task_impl_base(_Ct, _Scheduler_arg)
2413     {
2414 #if defined(__cplusplus_winrt)
2415         _M_unwrapped_async_op = nullptr;
2416 #endif /* defined (__cplusplus_winrt) */
2417     }
2418 
2419     virtual ~_Task_impl()
2420     {
2421         // We must invoke _DeregisterCancellation in the derived class destructor. Calling it in the base class
2422         // destructor could cause a partially initialized _Task_impl to be in the list of registrations for a
2423         // cancellation token.
2424         _DeregisterCancellation();
2425     }
2426 
2427     virtual bool _CancelAndRunContinuations(bool _SynchronousCancel,
2428                                             bool _UserException,
2429                                             bool _PropagatedFromAncestor,
2430                                             const std::shared_ptr<_ExceptionHolder>& _ExceptionHolder_arg)
2431     {
2432         bool _RunContinuations = false;
2433         {
2434             ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2435             if (_UserException)
2436             {
2437                 _ASSERTE(_SynchronousCancel && !_IsCompleted());
2438                 // If the state is _Canceled, the exception has to be coming from an ancestor.
2439                 _ASSERTE(!_IsCanceled() || _PropagatedFromAncestor);
2440 
2441                 // We should not be canceled with an exception more than once.
2442                 _ASSERTE(!_HasUserException());
2443 
2444                 // Mark _PropagatedFromAncestor as used.
2445                 (void)_PropagatedFromAncestor;
2446 
2447                 if (_M_TaskState == _Canceled)
2448                 {
2449                     // If the task has finished canceling there should not be any continuation records in the array.
2450                     return false;
2451                 }
2452                 else
2453                 {
2454                     _ASSERTE(_M_TaskState != _Completed);
2455                     _M_exceptionHolder = _ExceptionHolder_arg;
2456                 }
2457             }
2458             else
2459             {
2460                 // Completed is a non-cancellable state, and if this is an asynchronous cancel, we're unable to do
2461                 // better than the last async cancel which is to say, cancellation is already initiated, so return
2462                 // early.
2463                 if (_IsCompleted() || _IsCanceled() || (_IsPendingCancel() && !_SynchronousCancel))
2464                 {
2465                     _ASSERTE(!_IsCompleted() || !_HasUserException());
2466                     return false;
2467                 }
2468                 _ASSERTE(!_SynchronousCancel || !_HasUserException());
2469             }
2470 
2471             if (_SynchronousCancel)
2472             {
2473                 // Be aware that this set must be done BEFORE _M_Scheduled being set, or race will happen between this
2474                 // and wait()
2475                 _M_TaskState = _Canceled;
2476                 // Cancellation completes the task, so all dependent tasks must be run to cancel them
2477                 // They are canceled when they begin running (see _RunContinuation) and see that their
2478                 // ancestor has been canceled.
2479                 _RunContinuations = true;
2480             }
2481             else
2482             {
2483                 _ASSERTE(!_UserException);
2484 
2485                 if (_IsStarted())
2486                 {
2487 #if defined(__cplusplus_winrt)
2488                     if (_M_unwrapped_async_op != nullptr)
2489                     {
2490                         // We will only try to cancel async operation but not unwrapped tasks, since unwrapped tasks
2491                         // cannot be canceled without its token.
2492                         _M_unwrapped_async_op->Cancel();
2493                     }
2494 #endif /* defined (__cplusplus_winrt) */
2495                     _M_TaskCollection._Cancel();
2496                 }
2497 
2498                 // The _M_TaskState variable transitions to _Canceled when cancellation is completed (the task is not
2499                 // executing user code anymore). In the case of a synchronous cancel, this can happen immediately,
2500                 // whereas with an asynchronous cancel, the task has to move from _Started to _PendingCancel before it
2501                 // can move to _Canceled when it is finished executing.
2502                 _M_TaskState = _PendingCancel;
2503 
2504                 _M_taskEventLogger._LogCancelTask();
2505             }
2506         }
2507 
2508         // Only execute continuations and mark the task as completed if we were able to move the task to the _Canceled
2509         // state.
2510         if (_RunContinuations)
2511         {
2512             _M_TaskCollection._Complete();
2513 
2514             if (_M_Continuations)
2515             {
2516                 // Scheduling cancellation with automatic inlining.
2517                 _ScheduleFuncWithAutoInline([=]() { _RunTaskContinuations(); }, details::_DefaultAutoInline);
2518             }
2519         }
2520         return true;
2521     }
2522 
2523     void _FinalizeAndRunContinuations(_ReturnType _Result)
2524     {
2525         _M_Result.Set(_Result);
2526 
2527         {
2528             //
2529             // Hold this lock to ensure continuations being concurrently either get added
2530             // to the _M_Continuations vector or wait for the result
2531             //
2532             ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2533 
2534             // A task could still be in the _Created state if it was created with a task_completion_event.
2535             // It could also be in the _Canceled state for the same reason.
2536             _ASSERTE(!_HasUserException() && !_IsCompleted());
2537             if (_IsCanceled())
2538             {
2539                 return;
2540             }
2541 
2542             // Always transition to "completed" state, even in the face of unacknowledged pending cancellation
2543             _M_TaskState = _Completed;
2544         }
2545         _M_TaskCollection._Complete();
2546         _RunTaskContinuations();
2547     }
2548 
2549     //
2550     // This method is invoked when the starts executing. The task returns early if this method returns true.
2551     //
2552     bool _TransitionedToStarted()
2553     {
2554         ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2555         // Canceled state could only result from antecedent task's canceled state, but that code path will not reach
2556         // here.
2557         _ASSERTE(!_IsCanceled());
2558         if (_IsPendingCancel()) return false;
2559 
2560         _ASSERTE(_IsCreated());
2561         _M_TaskState = _Started;
2562         return true;
2563     }
2564 
2565 #if defined(__cplusplus_winrt)
2566     void _SetUnwrappedAsyncOp(_AsyncOperationType ^ _AsyncOp)
2567     {
2568         ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2569         // Cancel the async operation if the task itself is canceled, since the thread that canceled the task missed it.
2570         if (_IsPendingCancel())
2571         {
2572             _ASSERTE(!_IsCanceled());
2573             _AsyncOp->Cancel();
2574         }
2575         else
2576         {
2577             _M_unwrapped_async_op = _AsyncOp;
2578         }
2579     }
2580 #endif /* defined (__cplusplus_winrt) */
2581 
2582     // Return true if the task has reached a terminal state
2583     bool _IsDone() { return _IsCompleted() || _IsCanceled(); }
2584 
2585     _ReturnType _GetResult() { return _M_Result.Get(); }
2586 
2587     _ResultHolder<_ReturnType> _M_Result; // this means that the result type must have a public default ctor.
2588 #if defined(__cplusplus_winrt)
2589     _AsyncOperationType ^ _M_unwrapped_async_op;
2590 #endif /* defined (__cplusplus_winrt) */
2591 };
2592 
2593 template<typename _ResultType>
2594 struct _Task_completion_event_impl
2595 {
2596 private:
2597     _Task_completion_event_impl(const _Task_completion_event_impl&);
2598     _Task_completion_event_impl& operator=(const _Task_completion_event_impl&);
2599 
2600 public:
2601     typedef std::vector<typename _Task_ptr<_ResultType>::_Type> _TaskList;
2602 
2603     _Task_completion_event_impl() : _M_fHasValue(false), _M_fIsCanceled(false) {}
2604 
2605     bool _HasUserException() { return _M_exceptionHolder != nullptr; }
2606 
2607     ~_Task_completion_event_impl()
2608     {
2609         for (auto _TaskIt = _M_tasks.begin(); _TaskIt != _M_tasks.end(); ++_TaskIt)
2610         {
2611             _ASSERTE(!_M_fHasValue && !_M_fIsCanceled);
2612             // Cancel the tasks since the event was never signaled or canceled.
2613             (*_TaskIt)->_Cancel(true);
2614         }
2615     }
2616 
2617     // We need to protect the loop over the array, so concurrent_vector would not have helped
2618     _TaskList _M_tasks;
2619     ::pplx::extensibility::critical_section_t _M_taskListCritSec;
2620     _ResultHolder<_ResultType> _M_value;
2621     std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2622     std::atomic<bool> _M_fHasValue;
2623     std::atomic<bool> _M_fIsCanceled;
2624 };
2625 
2626 // Utility method for dealing with void functions
2627 inline std::function<_Unit_type(void)> _MakeVoidToUnitFunc(const std::function<void(void)>& _Func)
2628 {
2629     return [=]() -> _Unit_type {
2630         _Func();
2631         return _Unit_type();
2632     };
2633 }
2634 
2635 template<typename _Type>
2636 std::function<_Type(_Unit_type)> _MakeUnitToTFunc(const std::function<_Type(void)>& _Func)
2637 {
2638     return [=](_Unit_type) -> _Type { return _Func(); };
2639 }
2640 
2641 template<typename _Type>
2642 std::function<_Unit_type(_Type)> _MakeTToUnitFunc(const std::function<void(_Type)>& _Func)
2643 {
2644     return [=](_Type t) -> _Unit_type {
2645         _Func(t);
2646         return _Unit_type();
2647     };
2648 }
2649 
2650 inline std::function<_Unit_type(_Unit_type)> _MakeUnitToUnitFunc(const std::function<void(void)>& _Func)
2651 {
2652     return [=](_Unit_type) -> _Unit_type {
2653         _Func();
2654         return _Unit_type();
2655     };
2656 }
2657 } // namespace details
2658 
2659 /// <summary>
2660 ///     The <c>task_completion_event</c> class allows you to delay the execution of a task until a condition is
2661 ///     satisfied, or start a task in response to an external event.
2662 /// </summary>
2663 /// <typeparam name="_ResultType">
2664 ///     The result type of this <c>task_completion_event</c> class.
2665 /// </typeparam>
2666 /// <remarks>
2667 ///     Use a task created from a task completion event when your scenario requires you to create a task that will
2668 ///     complete, and thereby have its continuations scheduled for execution, at some point in the future. The
2669 ///     <c>task_completion_event</c> must have the same type as the task you create, and calling the set method on the
2670 ///     task completion event with a value of that type will cause the associated task to complete, and provide that
2671 ///     value as a result to its continuations. <para>If the task completion event is never signaled, any tasks created
2672 ///     from it will be canceled when it is destructed.</para> <para><c>task_completion_event</c> behaves like a smart
2673 ///     pointer, and should be passed by value.</para>
2674 /// </remarks>
2675 /// <seealso cref="task Class"/>
2676 /**/
2677 template<typename _ResultType>
2678 class task_completion_event
2679 {
2680 public:
2681     /// <summary>
2682     ///     Constructs a <c>task_completion_event</c> object.
2683     /// </summary>
2684     /**/
2685     task_completion_event() : _M_Impl(std::make_shared<details::_Task_completion_event_impl<_ResultType>>()) {}
2686 
2687     /// <summary>
2688     ///     Sets the task completion event.
2689     /// </summary>
2690     /// <param name="_Result">
2691     ///     The result to set this event with.
2692     /// </param>
2693     /// <returns>
2694     ///     The method returns <c>true</c> if it was successful in setting the event. It returns <c>false</c> if the
2695     ///     event is already set.
2696     /// </returns>
2697     /// <remarks>
2698     ///     In the presence of multiple or concurrent calls to <c>set</c>, only the first call will succeed and its
2699     ///     result (if any) will be stored in the task completion event. The remaining sets are ignored and the method
2700     ///     will return false. When you set a task completion event, all the tasks created from that event will
2701     ///     immediately complete, and its continuations, if any, will be scheduled. Task completion objects that have a
2702     ///     <typeparamref name="_ResultType"/> other than <c>void</c> will pass the value <paramref value="_Result"/> to
2703     ///     their continuations.
2704     /// </remarks>
2705     /**/
2706     bool set(_ResultType _Result)
2707         const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2708     {
2709         // Subsequent sets are ignored. This makes races to set benign: the first setter wins and all others are
2710         // ignored.
2711         if (_IsTriggered())
2712         {
2713             return false;
2714         }
2715 
2716         _TaskList _Tasks;
2717         bool _RunContinuations = false;
2718         {
2719             ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2720 
2721             if (!_IsTriggered())
2722             {
2723                 _M_Impl->_M_value.Set(_Result);
2724                 _M_Impl->_M_fHasValue = true;
2725 
2726                 _Tasks.swap(_M_Impl->_M_tasks);
2727                 _RunContinuations = true;
2728             }
2729         }
2730 
2731         if (_RunContinuations)
2732         {
2733             for (auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt)
2734             {
2735                 // If current task was canceled by a cancellation_token, it would be in cancel pending state.
2736                 if ((*_TaskIt)->_IsPendingCancel())
2737                     (*_TaskIt)->_Cancel(true);
2738                 else
2739                 {
2740                     // Tasks created with task_completion_events can be marked as async, (we do this in when_any and
2741                     // when_all if one of the tasks involved is an async task). Since continuations of async tasks can
2742                     // execute inline, we need to run continuations after the lock is released.
2743                     (*_TaskIt)->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2744                 }
2745             }
2746             if (_M_Impl->_HasUserException())
2747             {
2748                 _M_Impl->_M_exceptionHolder.reset();
2749             }
2750             return true;
2751         }
2752 
2753         return false;
2754     }
2755 
2756     template<typename _E>
2757     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2758         bool set_exception(
2759             _E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2760     {
2761         // It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for
2762         // set_exception.
2763         return _Cancel(std::make_exception_ptr(_Except), PPLX_CAPTURE_CALLSTACK());
2764     }
2765 
2766     /// <summary>
2767     ///     Propagates an exception to all tasks associated with this event.
2768     /// </summary>
2769     /// <param>
2770     ///     The exception_ptr that indicates the exception to set this event with.
2771     /// </param>
2772     /**/
2773     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
2774         bool set_exception(std::exception_ptr _ExceptionPtr)
2775             const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2776     {
2777         // It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for
2778         // set_exception.
2779         return _Cancel(_ExceptionPtr, PPLX_CAPTURE_CALLSTACK());
2780     }
2781 
2782     /// <summary>
2783     ///     Internal method to cancel the task_completion_event. Any task created using this event will be marked as
2784     ///     canceled if it has not already been set.
2785     /// </summary>
2786     bool _Cancel() const
2787     {
2788         // Cancel with the stored exception if one exists.
2789         return _CancelInternal();
2790     }
2791 
2792     /// <summary>
2793     ///     Internal method to cancel the task_completion_event with the exception provided. Any task created using this
2794     ///     event will be canceled with the same exception.
2795     /// </summary>
2796     template<typename _ExHolderType>
2797     bool _Cancel(
2798         _ExHolderType _ExHolder,
2799         const details::_TaskCreationCallstack& _SetExceptionAddressHint = details::_TaskCreationCallstack()) const
2800     {
2801         bool _Canceled;
2802         if (_StoreException(_ExHolder, _SetExceptionAddressHint))
2803         {
2804             _Canceled = _CancelInternal();
2805             _ASSERTE(_Canceled);
2806         }
2807         else
2808         {
2809             _Canceled = false;
2810         }
2811         return _Canceled;
2812     }
2813 
2814     /// <summary>
2815     ///     Internal method that stores an exception in the task completion event. This is used internally by when_any.
2816     ///     Note, this does not cancel the task completion event. A task completion event with a stored exception
2817     ///     can bet set() successfully. If it is canceled, it will cancel with the stored exception, if one is present.
2818     /// </summary>
2819     template<typename _ExHolderType>
2820     bool _StoreException(
2821         _ExHolderType _ExHolder,
2822         const details::_TaskCreationCallstack& _SetExceptionAddressHint = details::_TaskCreationCallstack()) const
2823     {
2824         ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2825         if (!_IsTriggered() && !_M_Impl->_HasUserException())
2826         {
2827             // Create the exception holder only if we have ensured there we will be successful in setting it onto the
2828             // task completion event. Failing to do so will result in an unobserved task exception.
2829             _M_Impl->_M_exceptionHolder = _ToExceptionHolder(_ExHolder, _SetExceptionAddressHint);
2830             return true;
2831         }
2832         return false;
2833     }
2834 
2835     /// <summary>
2836     ///     Tests whether current event has been either Set, or Canceled.
2837     /// </summary>
2838     bool _IsTriggered() const { return _M_Impl->_M_fHasValue || _M_Impl->_M_fIsCanceled; }
2839 
2840 private:
2841     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(
2842         const std::shared_ptr<details::_ExceptionHolder>& _ExHolder, const details::_TaskCreationCallstack&)
2843     {
2844         return _ExHolder;
2845     }
2846 
2847     static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(
2848         std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack& _SetExceptionAddressHint)
2849     {
2850         return std::make_shared<details::_ExceptionHolder>(_ExceptionPtr, _SetExceptionAddressHint);
2851     }
2852 
2853     template<typename T>
2854     friend class task; // task can register itself with the event by calling the private _RegisterTask
2855     template<typename T>
2856     friend class task_completion_event;
2857 
2858     typedef typename details::_Task_completion_event_impl<_ResultType>::_TaskList _TaskList;
2859 
2860     /// <summary>
2861     ///    Cancels the task_completion_event.
2862     /// </summary>
2863     bool _CancelInternal() const
2864     {
2865         // Cancellation of task completion events is an internal only utility. Our usage is such that _CancelInternal
2866         // will never be invoked if the task completion event has been set.
2867         _ASSERTE(!_M_Impl->_M_fHasValue);
2868         if (_M_Impl->_M_fIsCanceled)
2869         {
2870             return false;
2871         }
2872 
2873         _TaskList _Tasks;
2874         bool _Cancel = false;
2875         {
2876             ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2877             _ASSERTE(!_M_Impl->_M_fHasValue);
2878             if (!_M_Impl->_M_fIsCanceled)
2879             {
2880                 _M_Impl->_M_fIsCanceled = true;
2881                 _Tasks.swap(_M_Impl->_M_tasks);
2882                 _Cancel = true;
2883             }
2884         }
2885 
2886         bool _UserException = _M_Impl->_HasUserException();
2887 
2888         if (_Cancel)
2889         {
2890             for (auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt)
2891             {
2892                 // Need to call this after the lock is released. See comments in set().
2893                 if (_UserException)
2894                 {
2895                     (*_TaskIt)->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2896                 }
2897                 else
2898                 {
2899                     (*_TaskIt)->_Cancel(true);
2900                 }
2901             }
2902         }
2903         return _Cancel;
2904     }
2905 
2906     /// <summary>
2907     ///     Register a task with this event. This function is called when a task is constructed using
2908     ///     a task_completion_event.
2909     /// </summary>
2910     void _RegisterTask(const typename details::_Task_ptr<_ResultType>::_Type& _TaskParam)
2911     {
2912         ::pplx::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2913 
2914         // If an exception was already set on this event, then cancel the task with the stored exception.
2915         if (_M_Impl->_HasUserException())
2916         {
2917             _TaskParam->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2918         }
2919         else if (_M_Impl->_M_fHasValue)
2920         {
2921             _TaskParam->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2922         }
2923         else
2924         {
2925             _M_Impl->_M_tasks.push_back(_TaskParam);
2926         }
2927     }
2928 
2929     std::shared_ptr<details::_Task_completion_event_impl<_ResultType>> _M_Impl;
2930 };
2931 
2932 /// <summary>
2933 ///     The <c>task_completion_event</c> class allows you to delay the execution of a task until a condition is
2934 ///     satisfied, or start a task in response to an external event.
2935 /// </summary>
2936 /// <remarks>
2937 ///     Use a task created from a task completion event when your scenario requires you to create a task that will
2938 ///     complete, and thereby have its continuations scheduled for execution, at some point in the future. The
2939 ///     <c>task_completion_event</c> must have the same type as the task you create, and calling the set method on the
2940 ///     task completion event with a value of that type will cause the associated task to complete, and provide that
2941 ///     value as a result to its continuations. <para>If the task completion event is never signaled, any tasks created
2942 ///     from it will be canceled when it is destructed.</para> <para><c>task_completion_event</c> behaves like a smart
2943 ///     pointer, and should be passed by value.</para>
2944 /// </remarks>
2945 /// <seealso cref="task Class"/>
2946 /**/
2947 template<>
2948 class task_completion_event<void>
2949 {
2950 public:
2951     /// <summary>
2952     ///     Sets the task completion event.
2953     /// </summary>
2954     /// <returns>
2955     ///     The method returns <c>true</c> if it was successful in setting the event. It returns <c>false</c> if the
2956     ///     event is already set.
2957     /// </returns>
2958     /// <remarks>
2959     ///     In the presence of multiple or concurrent calls to <c>set</c>, only the first call will succeed and its
2960     ///     result (if any) will be stored in the task completion event. The remaining sets are ignored and the method
2961     ///     will return false. When you set a task completion event, all the tasks created from that event will
2962     ///     immediately complete, and its continuations, if any, will be scheduled. Task completion objects that have a
2963     ///     <typeparamref name="_ResultType"/> other than <c>void</c> will pass the value <paramref value="_Result"/> to
2964     ///     their continuations.
2965     /// </remarks>
2966     /**/
2967     bool set() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2968     {
2969         return _M_unitEvent.set(details::_Unit_type());
2970     }
2971 
2972     template<typename _E>
2973     __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2974         bool set_exception(
2975             _E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2976     {
2977         return _M_unitEvent._Cancel(std::make_exception_ptr(_Except), PPLX_CAPTURE_CALLSTACK());
2978     }
2979 
2980     /// <summary>
2981     ///     Propagates an exception to all tasks associated with this event.
2982     /// </summary>
2983     /// <param>
2984     ///     The exception_ptr that indicates the exception to set this event with.
2985     /// </param>
2986     /**/
2987     __declspec(
2988         noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK intrinsic gives us the expected result
2989         bool set_exception(std::exception_ptr _ExceptionPtr)
2990             const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2991     {
2992         // It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for
2993         // set_exception.
2994         return _M_unitEvent._Cancel(_ExceptionPtr, PPLX_CAPTURE_CALLSTACK());
2995     }
2996 
2997     /// <summary>
2998     ///     Cancel the task_completion_event. Any task created using this event will be marked as canceled if it has
2999     ///     not already been set.
3000     /// </summary>
3001     void _Cancel() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
3002     {
3003         _M_unitEvent._Cancel();
3004     }
3005 
3006     /// <summary>
3007     ///     Cancel the task_completion_event with the exception holder provided. Any task created using this event will
3008     ///     be canceled with the same exception.
3009     /// </summary>
3010     void _Cancel(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const { _M_unitEvent._Cancel(_ExHolder); }
3011 
3012     /// <summary>
3013     ///     Method that stores an exception in the task completion event. This is used internally by when_any.
3014     ///     Note, this does not cancel the task completion event. A task completion event with a stored exception
3015     ///     can bet set() successfully. If it is canceled, it will cancel with the stored exception, if one is present.
3016     /// </summary>
3017     bool _StoreException(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
3018     {
3019         return _M_unitEvent._StoreException(_ExHolder);
3020     }
3021 
3022     /// <summary>
3023     ///     Test whether current event has been either Set, or Canceled.
3024     /// </summary>
3025     bool _IsTriggered() const { return _M_unitEvent._IsTriggered(); }
3026 
3027 private:
3028     template<typename T>
3029     friend class task; // task can register itself with the event by calling the private _RegisterTask
3030 
3031     /// <summary>
3032     ///     Register a task with this event. This function is called when a task is constructed using
3033     ///     a task_completion_event.
3034     /// </summary>
3035     void _RegisterTask(details::_Task_ptr<details::_Unit_type>::_Type _TaskParam)
3036     {
3037         _M_unitEvent._RegisterTask(_TaskParam);
3038     }
3039 
3040     // The void event contains an event a dummy type so common code can be used for events with void and non-void
3041     // results.
3042     task_completion_event<details::_Unit_type> _M_unitEvent;
3043 };
3044 
3045 namespace details
3046 {
3047 //
3048 // Compile-time validation helpers
3049 //
3050 
3051 // Task constructor validation: issue helpful diagnostics for common user errors. Do not attempt full validation here.
3052 //
3053 // Anything callable is fine
3054 template<typename _ReturnType, typename _Ty>
3055 auto _IsValidTaskCtor(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type());
3056 
3057 #if defined(__cplusplus_winrt)
3058 // Anything that has GetResults is fine: this covers all async operations
3059 template<typename _ReturnType, typename _Ty>
3060 auto _IsValidTaskCtor(_Ty _Param, int, int, int, ...) -> decltype(_Param->GetResults(), std::true_type());
3061 #endif
3062 
3063 // Allow parameters with set: this covers task_completion_event
3064 template<typename _ReturnType, typename _Ty>
3065 auto _IsValidTaskCtor(_Ty _Param, int, int, ...)
3066     -> decltype(_Param.set(stdx::declval<_ReturnType>()), std::true_type());
3067 
3068 template<typename _ReturnType, typename _Ty>
3069 auto _IsValidTaskCtor(_Ty _Param, int, ...) -> decltype(_Param.set(), std::true_type());
3070 
3071 // All else is invalid
3072 template<typename _ReturnType, typename _Ty>
3073 std::false_type _IsValidTaskCtor(_Ty _Param, ...);
3074 
3075 template<typename _ReturnType, typename _Ty>
3076 void _ValidateTaskConstructorArgs(_Ty _Param)
3077 {
3078     static_assert(std::is_same<decltype(_IsValidTaskCtor<_ReturnType>(_Param, 0, 0, 0, 0)), std::true_type>::value,
3079 #if defined(__cplusplus_winrt)
3080                   "incorrect argument for task constructor; can be a callable object, an asynchronous operation, or a "
3081                   "task_completion_event"
3082 #else  /* defined (__cplusplus_winrt) */
3083                   "incorrect argument for task constructor; can be a callable object or a task_completion_event"
3084 #endif /* defined (__cplusplus_winrt) */
3085     );
3086 #if defined(__cplusplus_winrt)
3087     static_assert(!(std::is_same<_Ty, _ReturnType>::value && details::_IsIAsyncInfo<_Ty>::_Value),
3088                   "incorrect template argument for task; consider using the return type of the async operation");
3089 #endif /* defined (__cplusplus_winrt) */
3090 }
3091 
3092 #if defined(__cplusplus_winrt)
3093 // Helpers for create_async validation
3094 //
3095 // A parameter lambda taking no arguments is valid
3096 template<typename _Ty>
3097 static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type());
3098 
3099 // A parameter lambda taking an cancellation_token argument is valid
3100 template<typename _Ty>
3101 static auto _IsValidCreateAsync(_Ty _Param, int, int, int, ...)
3102     -> decltype(_Param(cancellation_token::none()), std::true_type());
3103 
3104 // A parameter lambda taking a progress report argument is valid
3105 template<typename _Ty>
3106 static auto _IsValidCreateAsync(_Ty _Param, int, int, ...)
3107     -> decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type());
3108 
3109 // A parameter lambda taking a progress report and a cancellation_token argument is valid
3110 template<typename _Ty>
3111 static auto _IsValidCreateAsync(_Ty _Param, int, ...)
3112     -> decltype(_Param(details::_ProgressReporterCtorArgType(), cancellation_token::none()), std::true_type());
3113 
3114 // All else is invalid
3115 template<typename _Ty>
3116 static std::false_type _IsValidCreateAsync(_Ty _Param, ...);
3117 #endif /* defined (__cplusplus_winrt) */
3118 
3119 /// <summary>
3120 ///     A helper class template that makes only movable functions be able to be passed to std::function
3121 /// </summary>
3122 template<typename _Ty>
3123 struct _NonCopyableFunctorWrapper
3124 {
3125     template<typename _Tx,
3126              typename = typename std::enable_if<
3127                  !std::is_base_of<_NonCopyableFunctorWrapper<_Ty>, typename std::decay<_Tx>::type>::value>::type>
3128     explicit _NonCopyableFunctorWrapper(_Tx&& f) : _M_functor {std::make_shared<_Ty>(std::forward<_Tx>(f))}
3129     {
3130     }
3131 
3132     template<class... _Args>
3133     auto operator()(_Args&&... args) -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
3134     {
3135         return _M_functor->operator()(std::forward<_Args>(args)...);
3136     }
3137 
3138     template<class... _Args>
3139     auto operator()(_Args&&... args) const -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
3140     {
3141         return _M_functor->operator()(std::forward<_Args>(args)...);
3142     }
3143 
3144     std::shared_ptr<_Ty> _M_functor;
3145 };
3146 
3147 template<typename _Ty, typename Enable = void>
3148 struct _CopyableFunctor
3149 {
3150     typedef _Ty _Type;
3151 };
3152 
3153 template<typename _Ty>
3154 struct _CopyableFunctor<
3155     _Ty,
3156     typename std::enable_if<std::is_move_constructible<_Ty>::value && !std::is_copy_constructible<_Ty>::value>::type>
3157 {
3158     typedef _NonCopyableFunctorWrapper<_Ty> _Type;
3159 };
3160 } // namespace details
3161 /// <summary>
3162 ///     A helper class template that transforms a continuation lambda that either takes or returns void, or both, into a
3163 ///     lambda that takes and returns a non-void type (details::_Unit_type is used to substitute for void). This is to
3164 ///     minimize the special handling required for 'void'.
3165 /// </summary>
3166 template<typename _InpType, typename _OutType>
3167 class _Continuation_func_transformer
3168 {
3169 public:
3170     static auto _Perform(std::function<_OutType(_InpType)> _Func) -> decltype(_Func) { return _Func; }
3171 };
3172 
3173 template<typename _OutType>
3174 class _Continuation_func_transformer<void, _OutType>
3175 {
3176 public:
3177     static auto _Perform(std::function<_OutType(void)> _Func) -> decltype(details::_MakeUnitToTFunc<_OutType>(_Func))
3178     {
3179         return details::_MakeUnitToTFunc<_OutType>(_Func);
3180     }
3181 };
3182 
3183 template<typename _InType>
3184 class _Continuation_func_transformer<_InType, void>
3185 {
3186 public:
3187     static auto _Perform(std::function<void(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc<_InType>(_Func))
3188     {
3189         return details::_MakeTToUnitFunc<_InType>(_Func);
3190     }
3191 };
3192 
3193 template<>
3194 class _Continuation_func_transformer<void, void>
3195 {
3196 public:
3197     static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
3198     {
3199         return details::_MakeUnitToUnitFunc(_Func);
3200     }
3201 };
3202 
3203 // A helper class template that transforms an intial task lambda returns void into a lambda that returns a non-void type
3204 // (details::_Unit_type is used to substitute for void). This is to minimize the special handling required for 'void'.
3205 template<typename _RetType>
3206 class _Init_func_transformer
3207 {
3208 public:
3209     static auto _Perform(std::function<_RetType(void)> _Func) -> decltype(_Func) { return _Func; }
3210 };
3211 
3212 template<>
3213 class _Init_func_transformer<void>
3214 {
3215 public:
3216     static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
3217     {
3218         return details::_MakeVoidToUnitFunc(_Func);
3219     }
3220 };
3221 
3222 /// <summary>
3223 ///     The Parallel Patterns Library (PPL) <c>task</c> class. A <c>task</c> object represents work that can be executed
3224 ///     asynchronously, and concurrently with other tasks and parallel work produced by parallel algorithms in the
3225 ///     Concurrency Runtime. It produces a result of type <typeparamref name="_ResultType"/> on successful completion.
3226 ///     Tasks of type <c>task&lt;void&gt;</c> produce no result. A task can be waited upon and canceled independently of
3227 ///     other tasks. It can also be composed with other tasks using continuations(<c>then</c>), and
3228 ///     join(<c>when_all</c>) and choice(<c>when_any</c>) patterns.
3229 /// </summary>
3230 /// <typeparam name="_ReturnType">
3231 ///     The result type of this task.
3232 /// </typeparam>
3233 /// <remarks>
3234 ///     For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.
3235 /// </remarks>
3236 /**/
3237 template<typename _ReturnType>
3238 class task
3239 {
3240 public:
3241     /// <summary>
3242     ///     The type of the result an object of this class produces.
3243     /// </summary>
3244     /**/
3245     typedef _ReturnType result_type;
3246 
3247     /// <summary>
3248     ///     Constructs a <c>task</c> object.
3249     /// </summary>
3250     /// <remarks>
3251     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
3252     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
3253     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
3254     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
3255     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
3256     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
3257     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
3258     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
3259     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
3260     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
3261     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
3262     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
3263     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
3264     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
3265     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
3266     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
3267     ///     Runtime)"/>.</para>
3268     /// </remarks>
3269     /**/
3270     task() : _M_Impl(nullptr)
3271     {
3272         // The default constructor should create a task with a nullptr impl. This is a signal that the
3273         // task is not usable and should throw if any wait(), get() or then() APIs are used.
3274     }
3275 
3276     /// <summary>
3277     ///     Constructs a <c>task</c> object.
3278     /// </summary>
3279     /// <typeparam name="_Ty">
3280     ///     The type of the parameter from which the task is to be constructed.
3281     /// </typeparam>
3282     /// <param name="_Param">
3283     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a
3284     ///     <c>task_completion_event&lt;result_type&gt;</c> object, or a Windows::Foundation::IAsyncInfo if you are
3285     ///     using tasks in your Windows Store app. The lambda or function object should be a type equivalent to
3286     ///     <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
3287     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
3288     /// </param>
3289     /// <param name="_Token">
3290     ///     The cancellation token to associate with this task. A task created without a cancellation token cannot be
3291     ///     canceled. It implicitly receives the token <c>cancellation_token::none()</c>.
3292     /// </param>
3293     /// <remarks>
3294     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
3295     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
3296     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
3297     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
3298     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
3299     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
3300     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
3301     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
3302     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
3303     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
3304     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
3305     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
3306     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
3307     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
3308     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
3309     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
3310     ///     Runtime)"/>.</para>
3311     /// </remarks>
3312     /**/
3313     template<typename _Ty>
3314     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
3315         explicit task(_Ty _Param)
3316     {
3317         task_options _TaskOptions;
3318         details::_ValidateTaskConstructorArgs<_ReturnType, _Ty>(_Param);
3319 
3320         _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3321         // Do not move the next line out of this function. It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the
3322         // the call site of the task constructor.
3323         _SetTaskCreationCallstack(PPLX_CAPTURE_CALLSTACK());
3324 
3325         _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param, 0));
3326     }
3327 
3328     /// <summary>
3329     ///     Constructs a <c>task</c> object.
3330     /// </summary>
3331     /// <typeparam name="_Ty">
3332     ///     The type of the parameter from which the task is to be constructed.
3333     /// </typeparam>
3334     /// <param name="_Param">
3335     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a
3336     ///     <c>task_completion_event&lt;result_type&gt;</c> object, or a Windows::Foundation::IAsyncInfo if you are
3337     ///     using tasks in your Windows Store app. The lambda or function object should be a type equivalent to
3338     ///     <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
3339     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
3340     /// </param>
3341     /// <param name="_TaskOptions">
3342     ///     The task options include cancellation token, scheduler etc
3343     /// </param>
3344     /// <remarks>
3345     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
3346     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
3347     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
3348     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
3349     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
3350     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
3351     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
3352     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
3353     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
3354     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
3355     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
3356     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
3357     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
3358     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
3359     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
3360     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
3361     ///     Runtime)"/>.</para>
3362     /// </remarks>
3363     /**/
3364     template<typename _Ty>
3365     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
3366         explicit task(_Ty _Param, const task_options& _TaskOptions)
3367     {
3368         details::_ValidateTaskConstructorArgs<_ReturnType, _Ty>(_Param);
3369 
3370         _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3371         // Do not move the next line out of this function. It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the
3372         // the call site of the task constructor.
3373         _SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack
3374                                       ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack
3375                                       : PPLX_CAPTURE_CALLSTACK());
3376 
3377         _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param, 0));
3378     }
3379 
3380     /// <summary>
3381     ///     Constructs a <c>task</c> object.
3382     /// </summary>
3383     /// <param name="_Other">
3384     ///     The source <c>task</c> object.
3385     /// </param>
3386     /// <remarks>
3387     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
3388     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
3389     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
3390     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
3391     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
3392     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
3393     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
3394     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
3395     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
3396     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
3397     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
3398     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
3399     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
3400     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
3401     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
3402     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
3403     ///     Runtime)"/>.</para>
3404     /// </remarks>
3405     /**/
3406     task(const task& _Other) : _M_Impl(_Other._M_Impl) {}
3407 
3408     /// <summary>
3409     ///     Constructs a <c>task</c> object.
3410     /// </summary>
3411     /// <param name="_Other">
3412     ///     The source <c>task</c> object.
3413     /// </param>
3414     /// <remarks>
3415     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
3416     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
3417     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
3418     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
3419     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
3420     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
3421     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
3422     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
3423     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
3424     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
3425     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
3426     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
3427     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
3428     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
3429     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
3430     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
3431     ///     Runtime)"/>.</para>
3432     /// </remarks>
3433     /**/
3434     task(task&& _Other) : _M_Impl(std::move(_Other._M_Impl)) {}
3435 
3436     /// <summary>
3437     ///     Replaces the contents of one <c>task</c> object with another.
3438     /// </summary>
3439     /// <param name="_Other">
3440     ///     The source <c>task</c> object.
3441     /// </param>
3442     /// <remarks>
3443     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents
3444     ///     the same actual task as <paramref name="_Other"/> does.
3445     /// </remarks>
3446     /**/
3447     task& operator=(const task& _Other)
3448     {
3449         if (this != &_Other)
3450         {
3451             _M_Impl = _Other._M_Impl;
3452         }
3453         return *this;
3454     }
3455 
3456     /// <summary>
3457     ///     Replaces the contents of one <c>task</c> object with another.
3458     /// </summary>
3459     /// <param name="_Other">
3460     ///     The source <c>task</c> object.
3461     /// </param>
3462     /// <remarks>
3463     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents
3464     ///     the same actual task as <paramref name="_Other"/> does.
3465     /// </remarks>
3466     /**/
3467     task& operator=(task&& _Other)
3468     {
3469         if (this != &_Other)
3470         {
3471             _M_Impl = std::move(_Other._M_Impl);
3472         }
3473         return *this;
3474     }
3475 
3476     /// <summary>
3477     ///     Adds a continuation task to this task.
3478     /// </summary>
3479     /// <typeparam name="_Function">
3480     ///     The type of the function object that will be invoked by this task.
3481     /// </typeparam>
3482     /// <param name="_Func">
3483     ///     The continuation function to execute when this task completes. This continuation function must take as input
3484     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the
3485     ///     type of the result this task produces.
3486     /// </param>
3487     /// <returns>
3488     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref
3489     ///     name="_Func"/> returns.
3490     /// </returns>
3491     /// <remarks>
3492     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo
3493     ///     interface, are only available to Windows Store apps. <para>For more information on how to use task
3494     ///     continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
3495     /// </remarks>
3496     /**/
3497     template<typename _Function>
3498     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
3499         auto then(_Function&& _Func) const ->
3500         typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3501     {
3502         task_options _TaskOptions;
3503         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
3504         return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
3505     }
3506 
3507     /// <summary>
3508     ///     Adds a continuation task to this task.
3509     /// </summary>
3510     /// <typeparam name="_Function">
3511     ///     The type of the function object that will be invoked by this task.
3512     /// </typeparam>
3513     /// <param name="_Func">
3514     ///     The continuation function to execute when this task completes. This continuation function must take as input
3515     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the
3516     ///     type of the result this task produces.
3517     /// </param>
3518     /// <param name="_TaskOptions">
3519     ///     The task options include cancellation token, scheduler and continuation context. By default the former 3
3520     ///     options are inherited from the antecedent task
3521     /// </param>
3522     /// <returns>
3523     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref
3524     ///     name="_Func"/> returns.
3525     /// </returns>
3526     /// <remarks>
3527     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo
3528     ///     interface, are only available to Windows Store apps. <para>For more information on how to use task
3529     ///     continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
3530     /// </remarks>
3531     /**/
3532     template<typename _Function>
3533     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
3534         auto then(_Function&& _Func, task_options _TaskOptions) const ->
3535         typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3536     {
3537         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
3538         return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
3539     }
3540 
3541     /// <summary>
3542     ///     Adds a continuation task to this task.
3543     /// </summary>
3544     /// <typeparam name="_Function">
3545     ///     The type of the function object that will be invoked by this task.
3546     /// </typeparam>
3547     /// <param name="_Func">
3548     ///     The continuation function to execute when this task completes. This continuation function must take as input
3549     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the
3550     ///     type of the result this task produces.
3551     /// </param>
3552     /// <param name="_CancellationToken">
3553     ///     The cancellation token to associate with the continuation task. A continuation task that is created without
3554     ///     a cancellation token will inherit the token of its antecedent task.
3555     /// </param>
3556     /// <param name="_ContinuationContext">
3557     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
3558     ///     Windows Store style app. For more information, see <see cref="task_continuation_context
3559     ///     Class">task_continuation_context</see>
3560     /// </param>
3561     /// <returns>
3562     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref
3563     ///     name="_Func"/> returns.
3564     /// </returns>
3565     /// <remarks>
3566     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo
3567     ///     interface, are only available to Windows Store apps. <para>For more information on how to use task
3568     ///     continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
3569     /// </remarks>
3570     /**/
3571     template<typename _Function>
3572     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
3573         auto then(_Function&& _Func,
3574                   cancellation_token _CancellationToken,
3575                   task_continuation_context _ContinuationContext) const ->
3576         typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3577     {
3578         task_options _TaskOptions(_CancellationToken, _ContinuationContext);
3579         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
3580         return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
3581     }
3582 
3583     /// <summary>
3584     ///     Waits for this task to reach a terminal state. It is possible for <c>wait</c> to execute the task inline, if
3585     ///     all of the tasks dependencies are satisfied, and it has not already been picked up for execution by a
3586     ///     background worker.
3587     /// </summary>
3588     /// <returns>
3589     ///     A <c>task_status</c> value which could be either <c>completed</c> or <c>canceled</c>. If the task
3590     ///     encountered an exception during execution, or an exception was propagated to it from an antecedent task,
3591     ///     <c>wait</c> will throw that exception.
3592     /// </returns>
3593     /**/
3594     task_status wait() const
3595     {
3596         if (!_M_Impl)
3597         {
3598             throw invalid_operation("wait() cannot be called on a default constructed task.");
3599         }
3600 
3601         return _M_Impl->_Wait();
3602     }
3603 
3604     /// <summary>
3605     ///     Returns the result this task produced. If the task is not in a terminal state, a call to <c>get</c> will
3606     ///     wait for the task to finish. This method does not return a value when called on a task with a
3607     ///     <c>result_type</c> of <c>void</c>.
3608     /// </summary>
3609     /// <returns>
3610     ///     The result of the task.
3611     /// </returns>
3612     /// <remarks>
3613     ///     If the task is canceled, a call to <c>get</c> will throw a <see cref="task_canceled
3614     ///     Class">task_canceled</see> exception. If the task encountered an different exception or an exception was
3615     ///     propagated to it from an antecedent task, a call to <c>get</c> will throw that exception.
3616     /// </remarks>
3617     /**/
3618     _ReturnType get() const
3619     {
3620         if (!_M_Impl)
3621         {
3622             throw invalid_operation("get() cannot be called on a default constructed task.");
3623         }
3624 
3625         if (_M_Impl->_Wait() == canceled)
3626         {
3627             throw task_canceled();
3628         }
3629 
3630         return _M_Impl->_GetResult();
3631     }
3632 
3633     /// <summary>
3634     ///     Determines if the task is completed.
3635     /// </summary>
3636     /// <returns>
3637     ///     True if the task has completed, false otherwise.
3638     /// </returns>
3639     /// <remarks>
3640     ///     The function returns true if the task is completed or canceled (with or without user exception).
3641     /// </remarks>
3642     bool is_done() const
3643     {
3644         if (!_M_Impl)
3645         {
3646             throw invalid_operation("is_done() cannot be called on a default constructed task.");
3647         }
3648 
3649         return _M_Impl->_IsDone();
3650     }
3651 
3652     /// <summary>
3653     ///     Returns the scheduler for this task
3654     /// </summary>
3655     /// <returns>
3656     ///     A pointer to the scheduler
3657     /// </returns>
3658     scheduler_ptr scheduler() const
3659     {
3660         if (!_M_Impl)
3661         {
3662             throw invalid_operation("scheduler() cannot be called on a default constructed task.");
3663         }
3664 
3665         return _M_Impl->_GetScheduler();
3666     }
3667 
3668     /// <summary>
3669     ///     Determines whether the task unwraps a Windows Runtime <c>IAsyncInfo</c> interface or is descended from such
3670     ///     a task.
3671     /// </summary>
3672     /// <returns>
3673     ///     <c>true</c> if the task unwraps an <c>IAsyncInfo</c> interface or is descended from such a task,
3674     ///     <c>false</c> otherwise.
3675     /// </returns>
3676     /**/
3677     bool is_apartment_aware() const
3678     {
3679         if (!_M_Impl)
3680         {
3681             throw invalid_operation("is_apartment_aware() cannot be called on a default constructed task.");
3682         }
3683         return _M_Impl->_IsApartmentAware();
3684     }
3685 
3686     /// <summary>
3687     ///     Determines whether two <c>task</c> objects represent the same internal task.
3688     /// </summary>
3689     /// <returns>
3690     ///     <c>true</c> if the objects refer to the same underlying task, and <c>false</c> otherwise.
3691     /// </returns>
3692     /**/
3693     bool operator==(const task<_ReturnType>& _Rhs) const { return (_M_Impl == _Rhs._M_Impl); }
3694 
3695     /// <summary>
3696     ///     Determines whether two <c>task</c> objects represent different internal tasks.
3697     /// </summary>
3698     /// <returns>
3699     ///     <c>true</c> if the objects refer to different underlying tasks, and <c>false</c> otherwise.
3700     /// </returns>
3701     /**/
3702     bool operator!=(const task<_ReturnType>& _Rhs) const { return !operator==(_Rhs); }
3703 
3704     /// <summary>
3705     ///     Create an underlying task implementation.
3706     /// </summary>
3707     void _CreateImpl(details::_CancellationTokenState* _Ct, scheduler_ptr _Scheduler)
3708     {
3709         _ASSERTE(_Ct != nullptr);
3710         _M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct, _Scheduler);
3711         if (_Ct != details::_CancellationTokenState::_None())
3712         {
3713             _M_Impl->_RegisterCancellation(_M_Impl);
3714         }
3715     }
3716 
3717     /// <summary>
3718     ///     Return the underlying implementation for this task.
3719     /// </summary>
3720     const typename details::_Task_ptr<_ReturnType>::_Type& _GetImpl() const { return _M_Impl; }
3721 
3722     /// <summary>
3723     ///     Set the implementation of the task to be the supplied implementation.
3724     /// </summary>
3725     void _SetImpl(const typename details::_Task_ptr<_ReturnType>::_Type& _Impl)
3726     {
3727         _ASSERTE(!_M_Impl);
3728         _M_Impl = _Impl;
3729     }
3730 
3731     /// <summary>
3732     ///     Set the implementation of the task to be the supplied implementation using a move instead of a copy.
3733     /// </summary>
3734     void _SetImpl(typename details::_Task_ptr<_ReturnType>::_Type&& _Impl)
3735     {
3736         _ASSERTE(!_M_Impl);
3737         _M_Impl = std::move(_Impl);
3738     }
3739 
3740     /// <summary>
3741     ///     Sets a property determining whether the task is apartment aware.
3742     /// </summary>
3743     void _SetAsync(bool _Async = true) { _GetImpl()->_SetAsync(_Async); }
3744 
3745     /// <summary>
3746     ///     Sets a field in the task impl to the return callstack for calls to the task constructors and the then
3747     ///     method.
3748     /// </summary>
3749     void _SetTaskCreationCallstack(const details::_TaskCreationCallstack& _callstack)
3750     {
3751         _GetImpl()->_SetTaskCreationCallstack(_callstack);
3752     }
3753 
3754     /// <summary>
3755     ///     An internal version of then that takes additional flags and always execute the continuation inline by
3756     ///     default. When _ForceInline is set to false, continuations inlining will be limited to default
3757     ///     _DefaultAutoInline. This function is Used for runtime internal continuations only.
3758     /// </summary>
3759     template<typename _Function>
3760     auto _Then(_Function&& _Func,
3761                details::_CancellationTokenState* _PTokenState,
3762                details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const ->
3763         typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3764     {
3765         // inherit from antecedent
3766         auto _Scheduler = _GetImpl()->_GetScheduler();
3767 
3768         return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func),
3769                                                  _PTokenState,
3770                                                  task_continuation_context::use_default(),
3771                                                  _Scheduler,
3772                                                  PPLX_CAPTURE_CALLSTACK(),
3773                                                  _InliningMode);
3774     }
3775 
3776 private:
3777     template<typename T>
3778     friend class task;
3779 
3780     // The task handle type used to construct an 'initial task' - a task with no dependents.
3781     template<typename _InternalReturnType, typename _Function, typename _TypeSelection>
3782     struct _InitialTaskHandle
3783         : details::_PPLTaskHandle<_ReturnType,
3784                                   _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>,
3785                                   details::_UnrealizedChore_t>
3786     {
3787         _Function _M_function;
3788         _InitialTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type& _TaskImpl, const _Function& _func)
3789             : details::_PPLTaskHandle<_ReturnType,
3790                                       _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>,
3791                                       details::_UnrealizedChore_t>::_PPLTaskHandle(_TaskImpl)
3792             , _M_function(_func)
3793         {
3794         }
3795 
3796         virtual ~_InitialTaskHandle() {}
3797 
3798         template<typename _Func>
3799         auto _LogWorkItemAndInvokeUserLambda(_Func&& _func) const -> decltype(_func())
3800         {
3801             details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3802             (void)_LogWorkItem;
3803             return _func();
3804         }
3805 
3806         void _Perform() const { _Init(_TypeSelection()); }
3807 
3808         void _SyncCancelAndPropagateException() const { this->_M_pTask->_Cancel(true); }
3809 
3810         //
3811         // Overload 0: returns _InternalReturnType
3812         //
3813         // This is the most basic task with no unwrapping
3814         //
3815         void _Init(details::_TypeSelectorNoAsync) const
3816         {
3817             this->_M_pTask->_FinalizeAndRunContinuations(
3818                 _LogWorkItemAndInvokeUserLambda(_Init_func_transformer<_InternalReturnType>::_Perform(_M_function)));
3819         }
3820 
3821         //
3822         // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only under /ZW)
3823         //                   or
3824         //             returns task<_InternalReturnType>
3825         //
3826         // This is task whose functor returns an async operation or a task which will be unwrapped for continuation
3827         // Depending on the output type, the right _AsyncInit gets invoked
3828         //
3829         void _Init(details::_TypeSelectorAsyncOperationOrTask) const
3830         {
3831             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(
3832                 this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_M_function));
3833         }
3834 
3835 #if defined(__cplusplus_winrt)
3836         //
3837         // Overload 2: returns IAsyncAction^
3838         //
3839         // This is task whose functor returns an async action which will be unwrapped for continuation
3840         //
3841         void _Init(details::_TypeSelectorAsyncAction) const
3842         {
3843             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(
3844                 this->_M_pTask,
3845                 ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(_M_function)));
3846         }
3847 
3848         //
3849         // Overload 3: returns IAsyncOperationWithProgress<_InternalReturnType, _ProgressType>^
3850         //
3851         // This is task whose functor returns an async operation with progress which will be unwrapped for continuation
3852         //
3853         void _Init(details::_TypeSelectorAsyncOperationWithProgress) const
3854         {
3855             typedef details::_GetProgressType<decltype(_M_function())>::_Value _ProgressType;
3856 
3857             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(
3858                 this->_M_pTask,
3859                 ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_InternalReturnType,
3860                                                                                        _ProgressType>(
3861                     _LogWorkItemAndInvokeUserLambda(_M_function)));
3862         }
3863 
3864         //
3865         // Overload 4: returns IAsyncActionWithProgress<_ProgressType>^
3866         //
3867         // This is task whose functor returns an async action with progress which will be unwrapped for continuation
3868         //
3869         void _Init(details::_TypeSelectorAsyncActionWithProgress) const
3870         {
3871             typedef details::_GetProgressType<decltype(_M_function())>::_Value _ProgressType;
3872 
3873             details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(
3874                 this->_M_pTask,
3875                 ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(
3876                     _LogWorkItemAndInvokeUserLambda(_M_function)));
3877         }
3878 #endif /* defined (__cplusplus_winrt) */
3879     };
3880 
3881     /// <summary>
3882     ///     The task handle type used to create a 'continuation task'.
3883     /// </summary>
3884     template<typename _InternalReturnType,
3885              typename _ContinuationReturnType,
3886              typename _Function,
3887              typename _IsTaskBased,
3888              typename _TypeSelection>
3889     struct _ContinuationTaskHandle
3890         : details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3891                                   _ContinuationTaskHandle<_InternalReturnType,
3892                                                           _ContinuationReturnType,
3893                                                           _Function,
3894                                                           _IsTaskBased,
3895                                                           _TypeSelection>,
3896                                   details::_ContinuationTaskHandleBase>
3897     {
3898         typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type
3899             _NormalizedContinuationReturnType;
3900 
3901         typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl;
3902         typename details::_CopyableFunctor<typename std::decay<_Function>::type>::_Type _M_function;
3903 
3904         template<class _ForwardedFunction>
3905         _ContinuationTaskHandle(
3906             const typename details::_Task_ptr<_ReturnType>::_Type& _AncestorImpl,
3907             const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type& _ContinuationImpl,
3908             _ForwardedFunction&& _Func,
3909             const task_continuation_context& _Context,
3910             details::_TaskInliningMode_t _InliningMode)
3911             : details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3912                                       _ContinuationTaskHandle<_InternalReturnType,
3913                                                               _ContinuationReturnType,
3914                                                               _Function,
3915                                                               _IsTaskBased,
3916                                                               _TypeSelection>,
3917                                       details::_ContinuationTaskHandleBase>::_PPLTaskHandle(_ContinuationImpl)
3918             , _M_ancestorTaskImpl(_AncestorImpl)
3919             , _M_function(std::forward<_ForwardedFunction>(_Func))
3920         {
3921             this->_M_isTaskBasedContinuation = _IsTaskBased::value;
3922             this->_M_continuationContext = _Context;
3923             this->_M_continuationContext._Resolve(_AncestorImpl->_IsApartmentAware());
3924             this->_M_inliningMode = _InliningMode;
3925         }
3926 
3927         virtual ~_ContinuationTaskHandle() {}
3928 
3929         template<typename _Func, typename _Arg>
3930         auto _LogWorkItemAndInvokeUserLambda(_Func&& _func, _Arg&& _value) const
3931             -> decltype(_func(std::forward<_Arg>(_value)))
3932         {
3933             details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3934             (void)_LogWorkItem;
3935             return _func(std::forward<_Arg>(_value));
3936         }
3937 
3938         void _Perform() const { _Continue(_IsTaskBased(), _TypeSelection()); }
3939 
3940         void _SyncCancelAndPropagateException() const
3941         {
3942             if (_M_ancestorTaskImpl->_HasUserException())
3943             {
3944                 // If the ancestor encountered an exception, transfer the exception to the continuation
3945                 // This traverses down the tree to propagate the exception.
3946                 this->_M_pTask->_CancelWithExceptionHolder(_M_ancestorTaskImpl->_GetExceptionHolder(), true);
3947             }
3948             else
3949             {
3950                 // If the ancestor was canceled, then your own execution should be canceled.
3951                 // This traverses down the tree to cancel it.
3952                 this->_M_pTask->_Cancel(true);
3953             }
3954         }
3955 
3956         //
3957         // Overload 0-0: _InternalReturnType -> _TaskType
3958         //
3959         // This is a straight task continuation which simply invokes its target with the ancestor's completion argument
3960         //
3961         void _Continue(std::false_type, details::_TypeSelectorNoAsync) const
3962         {
3963             this->_M_pTask->_FinalizeAndRunContinuations(_LogWorkItemAndInvokeUserLambda(
3964                 _Continuation_func_transformer<_InternalReturnType, _ContinuationReturnType>::_Perform(_M_function),
3965                 _M_ancestorTaskImpl->_GetResult()));
3966         }
3967 
3968         //
3969         // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>^ (only under /ZW)
3970         //               or
3971         //               _InternalReturnType -> task<_TaskType>
3972         //
3973         // This is a straight task continuation which returns an async operation or a task which will be unwrapped for
3974         // continuation Depending on the output type, the right _AsyncInit gets invoked
3975         //
3976         void _Continue(std::false_type, details::_TypeSelectorAsyncOperationOrTask) const
3977         {
3978             typedef typename details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
3979 
3980             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3981                 this->_M_pTask,
3982                 _LogWorkItemAndInvokeUserLambda(
3983                     _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function),
3984                     _M_ancestorTaskImpl->_GetResult()));
3985         }
3986 
3987 #if defined(__cplusplus_winrt)
3988         //
3989         // Overload 0-2: _InternalReturnType -> IAsyncAction^
3990         //
3991         // This is a straight task continuation which returns an async action which will be unwrapped for continuation
3992         //
3993         void _Continue(std::false_type, details::_TypeSelectorAsyncAction) const
3994         {
3995             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
3996 
3997             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3998                 this->_M_pTask,
3999                 ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(
4000                     _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function),
4001                     _M_ancestorTaskImpl->_GetResult())));
4002         }
4003 
4004         //
4005         // Overload 0-3: _InternalReturnType -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
4006         //
4007         // This is a straight task continuation which returns an async operation with progress which will be unwrapped
4008         // for continuation
4009         //
4010         void _Continue(std::false_type, details::_TypeSelectorAsyncOperationWithProgress) const
4011         {
4012             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
4013 
4014             auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(
4015                 _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function),
4016                 _M_ancestorTaskImpl->_GetResult());
4017             typedef details::_GetProgressType<decltype(_OpWithProgress)>::_Value _ProgressType;
4018 
4019             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4020                 this->_M_pTask,
4021                 ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType,
4022                                                                                        _ProgressType>(_OpWithProgress));
4023         }
4024 
4025         //
4026         // Overload 0-4: _InternalReturnType -> IAsyncActionWithProgress<_ProgressType>^
4027         //
4028         // This is a straight task continuation which returns an async action with progress which will be unwrapped for
4029         // continuation
4030         //
4031         void _Continue(std::false_type, details::_TypeSelectorAsyncActionWithProgress) const
4032         {
4033             typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
4034 
4035             auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(
4036                 _Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function),
4037                 _M_ancestorTaskImpl->_GetResult());
4038             typedef details::_GetProgressType<decltype(_OpWithProgress)>::_Value _ProgressType;
4039 
4040             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4041                 this->_M_pTask,
4042                 ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_OpWithProgress));
4043         }
4044 
4045 #endif /* defined (__cplusplus_winrt) */
4046 
4047         //
4048         // Overload 1-0: task<_InternalReturnType> -> _TaskType
4049         //
4050         // This is an exception handling type of continuation which takes the task rather than the task's result.
4051         //
4052         void _Continue(std::true_type, details::_TypeSelectorNoAsync) const
4053         {
4054             typedef task<_InternalReturnType> _FuncInputType;
4055             task<_InternalReturnType> _ResultTask;
4056             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
4057             this->_M_pTask->_FinalizeAndRunContinuations(_LogWorkItemAndInvokeUserLambda(
4058                 _Continuation_func_transformer<_FuncInputType, _ContinuationReturnType>::_Perform(_M_function),
4059                 std::move(_ResultTask)));
4060         }
4061 
4062         //
4063         // Overload 1-1: task<_InternalReturnType> -> IAsyncOperation<_TaskType>^
4064         //                                            or
4065         //                                            task<_TaskType>
4066         //
4067         // This is an exception handling type of continuation which takes the task rather than
4068         // the task's result. It also returns an async operation or a task which will be unwrapped
4069         // for continuation
4070         //
4071         void _Continue(std::true_type, details::_TypeSelectorAsyncOperationOrTask) const
4072         {
4073             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
4074             task<_InternalReturnType> _ResultTask;
4075             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
4076             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4077                 this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask)));
4078         }
4079 
4080 #if defined(__cplusplus_winrt)
4081 
4082         //
4083         // Overload 1-2: task<_InternalReturnType> -> IAsyncAction^
4084         //
4085         // This is an exception handling type of continuation which takes the task rather than
4086         // the task's result. It also returns an async action which will be unwrapped for continuation
4087         //
4088         void _Continue(std::true_type, details::_TypeSelectorAsyncAction) const
4089         {
4090             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
4091             task<_InternalReturnType> _ResultTask;
4092             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
4093             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4094                 this->_M_pTask,
4095                 ref new details::_IAsyncActionToAsyncOperationConverter(
4096                     _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
4097         }
4098 
4099         //
4100         // Overload 1-3: task<_InternalReturnType> -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
4101         //
4102         // This is an exception handling type of continuation which takes the task rather than
4103         // the task's result. It also returns an async operation with progress which will be unwrapped
4104         // for continuation
4105         //
4106         void _Continue(std::true_type, details::_TypeSelectorAsyncOperationWithProgress) const
4107         {
4108             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
4109             task<_InternalReturnType> _ResultTask;
4110             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
4111 
4112             typedef details::_GetProgressType<decltype(_M_function(_ResultTask))>::_Value _ProgressType;
4113 
4114             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4115                 this->_M_pTask,
4116                 ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType,
4117                                                                                        _ProgressType>(
4118                     _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
4119         }
4120 
4121         //
4122         // Overload 1-4: task<_InternalReturnType> -> IAsyncActionWithProgress<_ProgressType>^
4123         //
4124         // This is an exception handling type of continuation which takes the task rather than
4125         // the task's result. It also returns an async operation with progress which will be unwrapped
4126         // for continuation
4127         //
4128         void _Continue(std::true_type, details::_TypeSelectorAsyncActionWithProgress) const
4129         {
4130             // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
4131             task<_InternalReturnType> _ResultTask;
4132             _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
4133 
4134             typedef details::_GetProgressType<decltype(_M_function(_ResultTask))>::_Value _ProgressType;
4135 
4136             details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
4137                 this->_M_pTask,
4138                 ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(
4139                     _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
4140         }
4141 #endif /* defined (__cplusplus_winrt) */
4142     };
4143 
4144     /// <summary>
4145     ///     Initializes a task using a lambda, function pointer or function object.
4146     /// </summary>
4147     template<typename _InternalReturnType, typename _Function>
4148     void _TaskInitWithFunctor(const _Function& _Func)
4149     {
4150         typedef typename details::_InitFunctorTypeTraits<_InternalReturnType, decltype(_Func())> _Async_type_traits;
4151 
4152         _M_Impl->_M_fFromAsync = _Async_type_traits::_IsAsyncTask;
4153         _M_Impl->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
4154         _M_Impl->_M_taskEventLogger._LogScheduleTask(false);
4155         _M_Impl->_ScheduleTask(
4156             new _InitialTaskHandle<_InternalReturnType, _Function, typename _Async_type_traits::_AsyncKind>(_GetImpl(),
4157                                                                                                             _Func),
4158             details::_NoInline);
4159     }
4160 
4161     /// <summary>
4162     ///     Initializes a task using a task completion event.
4163     /// </summary>
4164     void _TaskInitNoFunctor(task_completion_event<_ReturnType>& _Event) { _Event._RegisterTask(_M_Impl); }
4165 
4166 #if defined(__cplusplus_winrt)
4167     /// <summary>
4168     ///     Initializes a task using an asynchronous operation IAsyncOperation<T>^
4169     /// </summary>
4170     void _TaskInitAsyncOp(
4171         Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value> ^ _AsyncOp)
4172     {
4173         _M_Impl->_M_fFromAsync = true;
4174 
4175         // Mark this task as started here since we can set the state in the constructor without acquiring a lock. Once
4176         // _AsyncInit returns a completion could execute concurrently and the task must be fully initialized before that
4177         // happens.
4178         _M_Impl->_M_TaskState = details::_Task_impl_base::_Started;
4179         // Pass the shared pointer into _AsyncInit for storage in the Async Callback.
4180         details::_Task_impl_base::_AsyncInit<_ReturnType, _ReturnType>(_M_Impl, _AsyncOp);
4181     }
4182 
4183     /// <summary>
4184     ///     Initializes a task using an asynchronous operation IAsyncOperation<T>^
4185     /// </summary>
4186     void _TaskInitNoFunctor(
4187         Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value> ^ _AsyncOp)
4188     {
4189         _TaskInitAsyncOp(_AsyncOp);
4190     }
4191 
4192     /// <summary>
4193     ///     Initializes a task using an asynchronous operation with progress IAsyncOperationWithProgress<T, P>^
4194     /// </summary>
4195     template<typename _Progress>
4196     void _TaskInitNoFunctor(
4197         Windows::Foundation::IAsyncOperationWithProgress<typename details::_ValueTypeOrRefType<_ReturnType>::_Value,
4198                                                          _Progress> ^
4199         _AsyncOp)
4200     {
4201         _TaskInitAsyncOp(ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<
4202                          typename details::_ValueTypeOrRefType<_ReturnType>::_Value,
4203                          _Progress>(_AsyncOp));
4204     }
4205 #endif /* defined (__cplusplus_winrt) */
4206 
4207     /// <summary>
4208     ///     Initializes a task using a callable object.
4209     /// </summary>
4210     template<typename _Function>
4211     void _TaskInitMaybeFunctor(_Function& _Func, std::true_type)
4212     {
4213         _TaskInitWithFunctor<_ReturnType, _Function>(_Func);
4214     }
4215 
4216     /// <summary>
4217     ///     Initializes a task using a non-callable object.
4218     /// </summary>
4219     template<typename _Ty>
4220     void _TaskInitMaybeFunctor(_Ty& _Param, std::false_type)
4221     {
4222         _TaskInitNoFunctor(_Param);
4223     }
4224 
4225     template<typename _InternalReturnType, typename _Function>
4226     auto _ThenImpl(_Function&& _Func, const task_options& _TaskOptions) const ->
4227         typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4228     {
4229         if (!_M_Impl)
4230         {
4231             throw invalid_operation("then() cannot be called on a default constructed task.");
4232         }
4233 
4234         details::_CancellationTokenState* _PTokenState =
4235             _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
4236         auto _Scheduler = _TaskOptions.has_scheduler() ? _TaskOptions.get_scheduler() : _GetImpl()->_GetScheduler();
4237         auto _CreationStack = details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack
4238                                   ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack
4239                                   : details::_TaskCreationCallstack();
4240         return _ThenImpl<_InternalReturnType, _Function>(std::forward<_Function>(_Func),
4241                                                          _PTokenState,
4242                                                          _TaskOptions.get_continuation_context(),
4243                                                          _Scheduler,
4244                                                          _CreationStack);
4245     }
4246 
4247     /// <summary>
4248     ///     The one and only implementation of then for void and non-void tasks.
4249     /// </summary>
4250     template<typename _InternalReturnType, typename _Function>
4251     auto _ThenImpl(_Function&& _Func,
4252                    details::_CancellationTokenState* _PTokenState,
4253                    const task_continuation_context& _ContinuationContext,
4254                    scheduler_ptr _Scheduler,
4255                    details::_TaskCreationCallstack _CreationStack,
4256                    details::_TaskInliningMode_t _InliningMode = details::_NoInline) const ->
4257         typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4258     {
4259         if (!_M_Impl)
4260         {
4261             throw invalid_operation("then() cannot be called on a default constructed task.");
4262         }
4263 
4264         typedef details::_FunctionTypeTraits<_Function, _InternalReturnType> _Function_type_traits;
4265         typedef details::_TaskTypeTraits<typename _Function_type_traits::_FuncRetType> _Async_type_traits;
4266         typedef typename _Async_type_traits::_TaskRetType _TaskType;
4267 
4268         //
4269         // A **nullptr** token state indicates that it was not provided by the user. In this case, we inherit the
4270         // antecedent's token UNLESS this is a an exception handling continuation. In that case, we break the chain with
4271         // a _None. That continuation is never canceled unless the user explicitly passes the same token.
4272         //
4273         if (_PTokenState == nullptr)
4274         {
4275             if (_Function_type_traits::_Takes_task::value)
4276             {
4277                 _PTokenState = details::_CancellationTokenState::_None();
4278             }
4279             else
4280             {
4281                 _PTokenState = _GetImpl()->_M_pTokenState;
4282             }
4283         }
4284 
4285         task<_TaskType> _ContinuationTask;
4286         _ContinuationTask._CreateImpl(_PTokenState, _Scheduler);
4287 
4288         _ContinuationTask._GetImpl()->_M_fFromAsync = (_GetImpl()->_M_fFromAsync || _Async_type_traits::_IsAsyncTask);
4289         _ContinuationTask._GetImpl()->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
4290         _ContinuationTask._SetTaskCreationCallstack(_CreationStack);
4291 
4292         _GetImpl()->_ScheduleContinuation(
4293             new _ContinuationTaskHandle<_InternalReturnType,
4294                                         _TaskType,
4295                                         _Function,
4296                                         typename _Function_type_traits::_Takes_task,
4297                                         typename _Async_type_traits::_AsyncKind>(_GetImpl(),
4298                                                                                  _ContinuationTask._GetImpl(),
4299                                                                                  std::forward<_Function>(_Func),
4300                                                                                  _ContinuationContext,
4301                                                                                  _InliningMode));
4302 
4303         return _ContinuationTask;
4304     }
4305 
4306     // The underlying implementation for this task
4307     typename details::_Task_ptr<_ReturnType>::_Type _M_Impl;
4308 };
4309 
4310 /// <summary>
4311 ///     The Parallel Patterns Library (PPL) <c>task</c> class. A <c>task</c> object represents work that can be executed
4312 ///     asynchronously, and concurrently with other tasks and parallel work produced by parallel algorithms in the
4313 ///     Concurrency Runtime. It produces a result of type <typeparamref name="_ResultType"/> on successful completion.
4314 ///     Tasks of type <c>task&lt;void&gt;</c> produce no result. A task can be waited upon and canceled independently of
4315 ///     other tasks. It can also be composed with other tasks using continuations(<c>then</c>), and
4316 ///     join(<c>when_all</c>) and choice(<c>when_any</c>) patterns.
4317 /// </summary>
4318 /// <remarks>
4319 ///     For more information, see <see cref="Task Parallelism (Concurrency Runtime)"/>.
4320 /// </remarks>
4321 /**/
4322 template<>
4323 class task<void>
4324 {
4325 public:
4326     /// <summary>
4327     ///     The type of the result an object of this class produces.
4328     /// </summary>
4329     /**/
4330     typedef void result_type;
4331 
4332     /// <summary>
4333     ///     Constructs a <c>task</c> object.
4334     /// </summary>
4335     /// <remarks>
4336     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
4337     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
4338     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
4339     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
4340     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
4341     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
4342     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
4343     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
4344     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4345     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
4346     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
4347     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
4348     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
4349     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
4350     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
4351     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
4352     ///     Runtime)"/>.</para>
4353     /// </remarks>
4354     /**/
4355     task() : _M_unitTask()
4356     {
4357         // The default constructor should create a task with a nullptr impl. This is a signal that the
4358         // task is not usable and should throw if any wait(), get() or then() APIs are used.
4359     }
4360 
4361     /// <summary>
4362     ///     Constructs a <c>task</c> object.
4363     /// </summary>
4364     /// <typeparam name="_Ty">
4365     ///     The type of the parameter from which the task is to be constructed.
4366     /// </typeparam>
4367     /// <param name="_Param">
4368     ///     The parameter from which the task is to be constructed. This could be a lambda, a function object, a
4369     ///     <c>task_completion_event&lt;result_type&gt;</c> object, or a Windows::Foundation::IAsyncInfo if you are
4370     ///     using tasks in your Windows Store app. The lambda or function object should be a type equivalent to
4371     ///     <c>std::function&lt;X(void)&gt;</c>, where X can be a variable of type <c>result_type</c>,
4372     ///     <c>task&lt;result_type&gt;</c>, or a Windows::Foundation::IAsyncInfo in Windows Store apps.
4373     /// </param>
4374     /// <remarks>
4375     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
4376     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
4377     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
4378     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
4379     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
4380     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
4381     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
4382     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
4383     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4384     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
4385     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
4386     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
4387     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
4388     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
4389     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
4390     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
4391     ///     Runtime)"/>.</para>
4392     /// </remarks>
4393     /**/
4394     template<typename _Ty>
4395     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
4396         explicit task(_Ty _Param, const task_options& _TaskOptions = task_options())
4397     {
4398         details::_ValidateTaskConstructorArgs<void, _Ty>(_Param);
4399 
4400         _M_unitTask._CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
4401         // Do not move the next line out of this function. It is important that PPLX_CAPTURE_CALLSTACK() evaluate to the
4402         // the call site of the task constructor.
4403         _M_unitTask._SetTaskCreationCallstack(
4404             details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack
4405                 ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack
4406                 : PPLX_CAPTURE_CALLSTACK());
4407 
4408         _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param, 0));
4409     }
4410 
4411     /// <summary>
4412     ///     Constructs a <c>task</c> object.
4413     /// </summary>
4414     /// <param name="_Other">
4415     ///     The source <c>task</c> object.
4416     /// </param>
4417     /// <remarks>
4418     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
4419     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
4420     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
4421     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
4422     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
4423     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
4424     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
4425     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
4426     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4427     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
4428     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
4429     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
4430     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
4431     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
4432     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
4433     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
4434     ///     Runtime)"/>.</para>
4435     /// </remarks>
4436     /**/
4437     task(const task& _Other) : _M_unitTask(_Other._M_unitTask) {}
4438 
4439     /// <summary>
4440     ///     Constructs a <c>task</c> object.
4441     /// </summary>
4442     /// <param name="_Other">
4443     ///     The source <c>task</c> object.
4444     /// </param>
4445     /// <remarks>
4446     ///     The default constructor for a <c>task</c> is only present in order to allow tasks to be used within
4447     ///     containers. A default constructed task cannot be used until you assign a valid task to it. Methods such as
4448     ///     <c>get</c>, <c>wait</c> or <c>then</c> will throw an <see cref="invalid_argument
4449     ///     Class">invalid_argument</see> exception when called on a default constructed task. <para>A task that is
4450     ///     created from a <c>task_completion_event</c> will complete (and have its continuations scheduled) when the
4451     ///     task completion event is set.</para> <para>The version of the constructor that takes a cancellation token
4452     ///     creates a task that can be canceled using the <c>cancellation_token_source</c> the token was obtained from.
4453     ///     Tasks created without a cancellation token are not cancelable.</para> <para>Tasks created from a
4454     ///     <c>Windows::Foundation::IAsyncInfo</c> interface or a lambda that returns an <c>IAsyncInfo</c> interface
4455     ///     reach their terminal state when the enclosed Windows Runtime asynchronous operation or action completes.
4456     ///     Similarly, tasks created from a lambda that returns a <c>task&lt;result_type&gt;</c> reach their terminal
4457     ///     state when the inner task reaches its terminal state, and not when the lambda returns.</para>
4458     ///     <para><c>task</c> behaves like a smart pointer and is safe to pass around by value. It can be accessed by
4459     ///     multiple threads without the need for locks.</para> <para>The constructor overloads that take a
4460     ///     Windows::Foundation::IAsyncInfo interface or a lambda returning such an interface, are only available to
4461     ///     Windows Store apps.</para> <para>For more information, see <see cref="Task Parallelism (Concurrency
4462     ///     Runtime)"/>.</para>
4463     /// </remarks>
4464     /**/
4465     task(task&& _Other) : _M_unitTask(std::move(_Other._M_unitTask)) {}
4466 
4467     /// <summary>
4468     ///     Replaces the contents of one <c>task</c> object with another.
4469     /// </summary>
4470     /// <param name="_Other">
4471     ///     The source <c>task</c> object.
4472     /// </param>
4473     /// <remarks>
4474     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents
4475     ///     the same actual task as <paramref name="_Other"/> does.
4476     /// </remarks>
4477     /**/
4478     task& operator=(const task& _Other)
4479     {
4480         if (this != &_Other)
4481         {
4482             _M_unitTask = _Other._M_unitTask;
4483         }
4484         return *this;
4485     }
4486 
4487     /// <summary>
4488     ///     Replaces the contents of one <c>task</c> object with another.
4489     /// </summary>
4490     /// <param name="_Other">
4491     ///     The source <c>task</c> object.
4492     /// </param>
4493     /// <remarks>
4494     ///     As <c>task</c> behaves like a smart pointer, after a copy assignment, this <c>task</c> objects represents
4495     ///     the same actual task as <paramref name="_Other"/> does.
4496     /// </remarks>
4497     /**/
4498     task& operator=(task&& _Other)
4499     {
4500         if (this != &_Other)
4501         {
4502             _M_unitTask = std::move(_Other._M_unitTask);
4503         }
4504         return *this;
4505     }
4506 
4507     /// <summary>
4508     ///     Adds a continuation task to this task.
4509     /// </summary>
4510     /// <typeparam name="_Function">
4511     ///     The type of the function object that will be invoked by this task.
4512     /// </typeparam>
4513     /// <param name="_Func">
4514     ///     The continuation function to execute when this task completes. This continuation function must take as input
4515     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the
4516     ///     type of the result this task produces.
4517     /// </param>
4518     /// <param name="_CancellationToken">
4519     ///     The cancellation token to associate with the continuation task. A continuation task that is created without
4520     ///     a cancellation token will inherit the token of its antecedent task.
4521     /// </param>
4522     /// <returns>
4523     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref
4524     ///     name="_Func"/> returns.
4525     /// </returns>
4526     /// <remarks>
4527     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo
4528     ///     interface, are only available to Windows Store apps. <para>For more information on how to use task
4529     ///     continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4530     /// </remarks>
4531     /**/
4532     template<typename _Function>
4533     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
4534         auto then(_Function&& _Func, task_options _TaskOptions = task_options()) const ->
4535         typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4536     {
4537         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
4538         return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func), _TaskOptions);
4539     }
4540 
4541     /// <summary>
4542     ///     Adds a continuation task to this task.
4543     /// </summary>
4544     /// <typeparam name="_Function">
4545     ///     The type of the function object that will be invoked by this task.
4546     /// </typeparam>
4547     /// <param name="_Func">
4548     ///     The continuation function to execute when this task completes. This continuation function must take as input
4549     ///     a variable of either <c>result_type</c> or <c>task&lt;result_type&gt;</c>, where <c>result_type</c> is the
4550     ///     type of the result this task produces.
4551     /// </param>
4552     /// <param name="_CancellationToken">
4553     ///     The cancellation token to associate with the continuation task. A continuation task that is created without
4554     ///     a cancellation token will inherit the token of its antecedent task.
4555     /// </param>
4556     /// <param name="_ContinuationContext">
4557     ///     A variable that specifies where the continuation should execute. This variable is only useful when used in a
4558     ///     Windows Store style app. For more information, see <see cref="task_continuation_context
4559     ///     Class">task_continuation_context</see>
4560     /// </param>
4561     /// <returns>
4562     ///     The newly created continuation task. The result type of the returned task is determined by what <paramref
4563     ///     name="_Func"/> returns.
4564     /// </returns>
4565     /// <remarks>
4566     ///     The overloads of <c>then</c> that take a lambda or functor that returns a Windows::Foundation::IAsyncInfo
4567     ///     interface, are only available to Windows Store apps. <para>For more information on how to use task
4568     ///     continuations to compose asynchronous work, see <see cref="Task Parallelism (Concurrency Runtime)"/>.</para>
4569     /// </remarks>
4570     /**/
4571     template<typename _Function>
4572     __declspec(noinline) // Ask for no inlining so that the PPLX_CAPTURE_CALLSTACK gives us the expected result
4573         auto then(_Function&& _Func,
4574                   cancellation_token _CancellationToken,
4575                   task_continuation_context _ContinuationContext) const ->
4576         typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4577     {
4578         task_options _TaskOptions(_CancellationToken, _ContinuationContext);
4579         details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
4580         return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func), _TaskOptions);
4581     }
4582 
4583     /// <summary>
4584     ///     Waits for this task to reach a terminal state. It is possible for <c>wait</c> to execute the task inline, if
4585     ///     all of the tasks dependencies are satisfied, and it has not already been picked up for execution by a
4586     ///     background worker.
4587     /// </summary>
4588     /// <returns>
4589     ///     A <c>task_status</c> value which could be either <c>completed</c> or <c>canceled</c>. If the task
4590     ///     encountered an exception during execution, or an exception was propagated to it from an antecedent task,
4591     ///     <c>wait</c> will throw that exception.
4592     /// </returns>
4593     /**/
4594     task_status wait() const { return _M_unitTask.wait(); }
4595 
4596     /// <summary>
4597     ///     Returns the result this task produced. If the task is not in a terminal state, a call to <c>get</c> will
4598     ///     wait for the task to finish. This method does not return a value when called on a task with a
4599     ///     <c>result_type</c> of <c>void</c>.
4600     /// </summary>
4601     /// <remarks>
4602     ///     If the task is canceled, a call to <c>get</c> will throw a <see cref="task_canceled
4603     ///     Class">task_canceled</see> exception. If the task encountered an different exception or an exception was
4604     ///     propagated to it from an antecedent task, a call to <c>get</c> will throw that exception.
4605     /// </remarks>
4606     /**/
4607     void get() const { _M_unitTask.get(); }
4608 
4609     /// <summary>
4610     ///     Determines if the task is completed.
4611     /// </summary>
4612     /// <returns>
4613     ///     True if the task has completed, false otherwise.
4614     /// </returns>
4615     /// <remarks>
4616     ///     The function returns true if the task is completed or canceled (with or without user exception).
4617     /// </remarks>
4618     bool is_done() const { return _M_unitTask.is_done(); }
4619 
4620     /// <summary>
4621     ///     Returns the scheduler for this task
4622     /// </summary>
4623     /// <returns>
4624     ///     A pointer to the scheduler
4625     /// </returns>
4626     scheduler_ptr scheduler() const { return _M_unitTask.scheduler(); }
4627 
4628     /// <summary>
4629     ///     Determines whether the task unwraps a Windows Runtime <c>IAsyncInfo</c> interface or is descended from such
4630     ///     a task.
4631     /// </summary>
4632     /// <returns>
4633     ///     <c>true</c> if the task unwraps an <c>IAsyncInfo</c> interface or is descended from such a task,
4634     ///     <c>false</c> otherwise.
4635     /// </returns>
4636     /**/
4637     bool is_apartment_aware() const { return _M_unitTask.is_apartment_aware(); }
4638 
4639     /// <summary>
4640     ///     Determines whether two <c>task</c> objects represent the same internal task.
4641     /// </summary>
4642     /// <returns>
4643     ///     <c>true</c> if the objects refer to the same underlying task, and <c>false</c> otherwise.
4644     /// </returns>
4645     /**/
4646     bool operator==(const task<void>& _Rhs) const { return (_M_unitTask == _Rhs._M_unitTask); }
4647 
4648     /// <summary>
4649     ///     Determines whether two <c>task</c> objects represent different internal tasks.
4650     /// </summary>
4651     /// <returns>
4652     ///     <c>true</c> if the objects refer to different underlying tasks, and <c>false</c> otherwise.
4653     /// </returns>
4654     /**/
4655     bool operator!=(const task<void>& _Rhs) const { return !operator==(_Rhs); }
4656 
4657     /// <summary>
4658     ///     Create an underlying task implementation.
4659     /// </summary>
4660     void _CreateImpl(details::_CancellationTokenState* _Ct, scheduler_ptr _Scheduler)
4661     {
4662         _M_unitTask._CreateImpl(_Ct, _Scheduler);
4663     }
4664 
4665     /// <summary>
4666     ///     Return the underlying implementation for this task.
4667     /// </summary>
4668     const details::_Task_ptr<details::_Unit_type>::_Type& _GetImpl() const { return _M_unitTask._M_Impl; }
4669 
4670     /// <summary>
4671     ///     Set the implementation of the task to be the supplied implementation.
4672     /// </summary>
4673     void _SetImpl(const details::_Task_ptr<details::_Unit_type>::_Type& _Impl) { _M_unitTask._SetImpl(_Impl); }
4674 
4675     /// <summary>
4676     ///     Set the implementation of the task to be the supplied implementation using a move instead of a copy.
4677     /// </summary>
4678     void _SetImpl(details::_Task_ptr<details::_Unit_type>::_Type&& _Impl) { _M_unitTask._SetImpl(std::move(_Impl)); }
4679 
4680     /// <summary>
4681     ///     Sets a property determining whether the task is apartment aware.
4682     /// </summary>
4683     void _SetAsync(bool _Async = true) { _M_unitTask._SetAsync(_Async); }
4684 
4685     /// <summary>
4686     ///     Sets a field in the task impl to the return callstack for calls to the task constructors and the then
4687     ///     method.
4688     /// </summary>
4689     void _SetTaskCreationCallstack(const details::_TaskCreationCallstack& _callstack)
4690     {
4691         _M_unitTask._SetTaskCreationCallstack(_callstack);
4692     }
4693 
4694     /// <summary>
4695     ///     An internal version of then that takes additional flags and executes the continuation inline. Used for
4696     ///     runtime internal continuations only.
4697     /// </summary>
4698     template<typename _Function>
4699     auto _Then(_Function&& _Func,
4700                details::_CancellationTokenState* _PTokenState,
4701                details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const ->
4702         typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4703     {
4704         // inherit from antecedent
4705         auto _Scheduler = _GetImpl()->_GetScheduler();
4706 
4707         return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func),
4708                                                       _PTokenState,
4709                                                       task_continuation_context::use_default(),
4710                                                       _Scheduler,
4711                                                       PPLX_CAPTURE_CALLSTACK(),
4712                                                       _InliningMode);
4713     }
4714 
4715 private:
4716     template<typename T>
4717     friend class task;
4718     template<typename T>
4719     friend class task_completion_event;
4720 
4721     /// <summary>
4722     ///     Initializes a task using a task completion event.
4723     /// </summary>
4724     void _TaskInitNoFunctor(task_completion_event<void>& _Event)
4725     {
4726         _M_unitTask._TaskInitNoFunctor(_Event._M_unitEvent);
4727     }
4728 
4729 #if defined(__cplusplus_winrt)
4730     /// <summary>
4731     ///     Initializes a task using an asynchronous action IAsyncAction^
4732     /// </summary>
4733     void _TaskInitNoFunctor(Windows::Foundation::IAsyncAction ^ _AsyncAction)
4734     {
4735         _M_unitTask._TaskInitAsyncOp(ref new details::_IAsyncActionToAsyncOperationConverter(_AsyncAction));
4736     }
4737 
4738     /// <summary>
4739     ///     Initializes a task using an asynchronous action with progress IAsyncActionWithProgress<_P>^
4740     /// </summary>
4741     template<typename _P>
4742     void _TaskInitNoFunctor(Windows::Foundation::IAsyncActionWithProgress<_P> ^ _AsyncActionWithProgress)
4743     {
4744         _M_unitTask._TaskInitAsyncOp(
4745             ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_P>(_AsyncActionWithProgress));
4746     }
4747 #endif /* defined (__cplusplus_winrt) */
4748 
4749     /// <summary>
4750     ///     Initializes a task using a callable object.
4751     /// </summary>
4752     template<typename _Function>
4753     void _TaskInitMaybeFunctor(_Function& _Func, std::true_type)
4754     {
4755         _M_unitTask._TaskInitWithFunctor<void, _Function>(_Func);
4756     }
4757 
4758     /// <summary>
4759     ///     Initializes a task using a non-callable object.
4760     /// </summary>
4761     template<typename _T>
4762     void _TaskInitMaybeFunctor(_T& _Param, std::false_type)
4763     {
4764         _TaskInitNoFunctor(_Param);
4765     }
4766 
4767     // The void task contains a task of a dummy type so common code can be used for tasks with void and non-void
4768     // results.
4769     task<details::_Unit_type> _M_unitTask;
4770 };
4771 
4772 namespace details
4773 {
4774 /// <summary>
4775 ///   The following type traits are used for the create_task function.
4776 /// </summary>
4777 
4778 #if defined(__cplusplus_winrt)
4779 // Unwrap functions for asyncOperations
4780 template<typename _Ty>
4781 _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperation<_Ty> ^);
4782 
4783 void _GetUnwrappedType(Windows::Foundation::IAsyncAction ^);
4784 
4785 template<typename _Ty, typename _Progress>
4786 _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress> ^);
4787 
4788 template<typename _Progress>
4789 void _GetUnwrappedType(Windows::Foundation::IAsyncActionWithProgress<_Progress> ^);
4790 #endif /* defined (__cplusplus_winrt) */
4791 
4792 // Unwrap task<T>
4793 template<typename _Ty>
4794 _Ty _GetUnwrappedType(task<_Ty>);
4795 
4796 // Unwrap all supported types
4797 template<typename _Ty>
4798 auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg));
4799 // fallback
4800 template<typename _Ty>
4801 _Ty _GetUnwrappedReturnType(_Ty, ...);
4802 
4803 /// <summary>
4804 ///   <c>_GetTaskType</c> functions will retrieve task type <c>T</c> in <c>task[T](Arg)</c>,
4805 ///   for given constructor argument <c>Arg</c> and its property "callable".
4806 ///   It will automatically unwrap argument to get the final return type if necessary.
4807 /// </summary>
4808 
4809 // Non-Callable
4810 template<typename _Ty>
4811 _Ty _GetTaskType(task_completion_event<_Ty>, std::false_type);
4812 
4813 // Non-Callable
4814 template<typename _Ty>
4815 auto _GetTaskType(_Ty _NonFunc, std::false_type) -> decltype(_GetUnwrappedType(_NonFunc));
4816 
4817 // Callable
4818 template<typename _Ty>
4819 auto _GetTaskType(_Ty _Func, std::true_type) -> decltype(_GetUnwrappedReturnType(_Func(), 0));
4820 
4821 // Special callable returns void
4822 void _GetTaskType(std::function<void()>, std::true_type);
4823 struct _BadArgType
4824 {
4825 };
4826 
4827 template<typename _Ty>
4828 auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable(_Param, 0)));
4829 
4830 template<typename _Ty>
4831 _BadArgType _FilterValidTaskType(_Ty _Param, ...);
4832 
4833 template<typename _Ty>
4834 struct _TaskTypeFromParam
4835 {
4836     typedef decltype(_FilterValidTaskType(stdx::declval<_Ty>(), 0)) _Type;
4837 };
4838 } // namespace details
4839 
4840 /// <summary>
4841 ///     Creates a PPL <see cref="task Class">task</see> object. <c>create_task</c> can be used anywhere you would have
4842 ///     used a task constructor. It is provided mainly for convenience, because it allows use of the <c>auto</c> keyword
4843 ///     while creating tasks.
4844 /// </summary>
4845 /// <typeparam name="_Ty">
4846 ///     The type of the parameter from which the task is to be constructed.
4847 /// </typeparam>
4848 /// <param name="_Param">
4849 ///     The parameter from which the task is to be constructed. This could be a lambda or function object, a
4850 ///     <c>task_completion_event</c> object, a different <c>task</c> object, or a Windows::Foundation::IAsyncInfo
4851 ///     interface if you are using tasks in your Windows Store app.
4852 /// </param>
4853 /// <returns>
4854 ///     A new task of type <c>T</c>, that is inferred from <paramref name="_Param"/>.
4855 /// </returns>
4856 /// <remarks>
4857 ///     The first overload behaves like a task constructor that takes a single parameter.
4858 ///     <para>The second overload associates the cancellation token provided with the newly created task. If you use
4859 ///     this overload you are not allowed to pass in a different <c>task</c> object as the first parameter.</para>
4860 ///     <para>The type of the returned task is inferred from the first parameter to the function. If <paramref
4861 ///     name="_Param"/> is a <c>task_completion_event&lt;T&gt;</c>, a <c>task&lt;T&gt;</c>, or a functor that returns
4862 ///     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>.</para>
4863 ///     <para>In a Windows Store app, if <paramref name="_Param"/> is of type
4864 ///     Windows::Foundation::IAsyncOperation&lt;T&gt;^ or Windows::Foundation::IAsyncOperationWithProgress&lt;T,P&gt;^,
4865 ///     or a functor that returns either of those types, the created task will be of type <c>task&lt;T&gt;</c>. If
4866 ///     <paramref name="_Param"/> is of type Windows::Foundation::IAsyncAction^ or
4867 ///     Windows::Foundation::IAsyncActionWithProgress&lt;P&gt;^, or a functor that returns either of those types, the
4868 ///     created task will have type <c>task&lt;void&gt;</c>.</para>
4869 /// </remarks>
4870 /// <seealso cref="task Class"/>
4871 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
4872 /**/
4873 template<typename _Ty>
4874 __declspec(noinline) auto create_task(_Ty _Param, task_options _TaskOptions = task_options())
4875     -> task<typename details::_TaskTypeFromParam<_Ty>::_Type>
4876 {
4877     static_assert(!std::is_same<typename details::_TaskTypeFromParam<_Ty>::_Type, details::_BadArgType>::value,
4878 #if defined(__cplusplus_winrt)
4879                   "incorrect argument for create_task; can be a callable object, an asynchronous operation, or a "
4880                   "task_completion_event"
4881 #else  /* defined (__cplusplus_winrt) */
4882                   "incorrect argument for create_task; can be a callable object or a task_completion_event"
4883 #endif /* defined (__cplusplus_winrt) */
4884     );
4885     details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(PPLX_CAPTURE_CALLSTACK());
4886     task<typename details::_TaskTypeFromParam<_Ty>::_Type> _CreatedTask(_Param, _TaskOptions);
4887     return _CreatedTask;
4888 }
4889 
4890 /// <summary>
4891 ///     Creates a PPL <see cref="task Class">task</see> object. <c>create_task</c> can be used anywhere you would have
4892 ///     used a task constructor. It is provided mainly for convenience, because it allows use of the <c>auto</c> keyword
4893 ///     while creating tasks.
4894 /// </summary>
4895 /// <typeparam name="_Ty">
4896 ///     The type of the parameter from which the task is to be constructed.
4897 /// </typeparam>
4898 /// <param name="_Param">
4899 ///     The parameter from which the task is to be constructed. This could be a lambda or function object, a
4900 ///     <c>task_completion_event</c> object, a different <c>task</c> object, or a Windows::Foundation::IAsyncInfo
4901 ///     interface if you are using tasks in your Windows Store app.
4902 /// </param>
4903 /// <param name="_Token">
4904 ///     The cancellation token to associate with the task. When the source for this token is canceled, cancellation will
4905 ///     be requested on the task.
4906 /// </param>
4907 /// <returns>
4908 ///     A new task of type <c>T</c>, that is inferred from <paramref name="_Param"/>.
4909 /// </returns>
4910 /// <remarks>
4911 ///     The first overload behaves like a task constructor that takes a single parameter.
4912 ///     <para>The second overload associates the cancellation token provided with the newly created task. If you use
4913 ///     this overload you are not allowed to pass in a different <c>task</c> object as the first parameter.</para>
4914 ///     <para>The type of the returned task is inferred from the first parameter to the function. If <paramref
4915 ///     name="_Param"/> is a <c>task_completion_event&lt;T&gt;</c>, a <c>task&lt;T&gt;</c>, or a functor that returns
4916 ///     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>.</para>
4917 ///     <para>In a Windows Store app, if <paramref name="_Param"/> is of type
4918 ///     Windows::Foundation::IAsyncOperation&lt;T&gt;^ or Windows::Foundation::IAsyncOperationWithProgress&lt;T,P&gt;^,
4919 ///     or a functor that returns either of those types, the created task will be of type <c>task&lt;T&gt;</c>. If
4920 ///     <paramref name="_Param"/> is of type Windows::Foundation::IAsyncAction^ or
4921 ///     Windows::Foundation::IAsyncActionWithProgress&lt;P&gt;^, or a functor that returns either of those types, the
4922 ///     created task will have type <c>task&lt;void&gt;</c>.</para>
4923 /// </remarks>
4924 /// <seealso cref="task Class"/>
4925 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
4926 /**/
4927 template<typename _ReturnType>
4928 __declspec(noinline) task<_ReturnType> create_task(const task<_ReturnType>& _Task)
4929 {
4930     task<_ReturnType> _CreatedTask(_Task);
4931     return _CreatedTask;
4932 }
4933 
4934 #if defined(__cplusplus_winrt)
4935 namespace details
4936 {
4937 template<typename _T>
4938 task<_T> _To_task_helper(Windows::Foundation::IAsyncOperation<_T> ^ op)
4939 {
4940     return task<_T>(op);
4941 }
4942 
4943 template<typename _T, typename _Progress>
4944 task<_T> _To_task_helper(Windows::Foundation::IAsyncOperationWithProgress<_T, _Progress> ^ op)
4945 {
4946     return task<_T>(op);
4947 }
4948 
4949 inline task<void> _To_task_helper(Windows::Foundation::IAsyncAction ^ op) { return task<void>(op); }
4950 
4951 template<typename _Progress>
4952 task<void> _To_task_helper(Windows::Foundation::IAsyncActionWithProgress<_Progress> ^ op)
4953 {
4954     return task<void>(op);
4955 }
4956 
4957 template<typename _ProgressType>
4958 class _ProgressDispatcherBase
4959 {
4960 public:
4961     virtual ~_ProgressDispatcherBase() {}
4962 
4963     virtual void _Report(const _ProgressType& _Val) = 0;
4964 };
4965 
4966 template<typename _ProgressType, typename _ClassPtrType>
4967 class _ProgressDispatcher : public _ProgressDispatcherBase<_ProgressType>
4968 {
4969 public:
4970     virtual ~_ProgressDispatcher() {}
4971 
4972     _ProgressDispatcher(_ClassPtrType _Ptr) : _M_ptr(_Ptr) {}
4973 
4974     virtual void _Report(const _ProgressType& _Val) { _M_ptr->_FireProgress(_Val); }
4975 
4976 private:
4977     _ClassPtrType _M_ptr;
4978 };
4979 class _ProgressReporterCtorArgType
4980 {
4981 };
4982 } // namespace details
4983 
4984 /// <summary>
4985 ///     The progress reporter class allows reporting progress notifications of a specific type. Each progress_reporter
4986 ///     object is bound to a particular asynchronous action or operation.
4987 /// </summary>
4988 /// <typeparam name="_ProgressType">
4989 ///     The payload type of each progress notification reported through the progress reporter.
4990 /// </typeparam>
4991 /// <remarks>
4992 ///     This type is only available to Windows Store apps.
4993 /// </remarks>
4994 /// <seealso cref="create_async Function"/>
4995 /**/
4996 template<typename _ProgressType>
4997 class progress_reporter
4998 {
4999     typedef std::shared_ptr<details::_ProgressDispatcherBase<_ProgressType>> _PtrType;
5000 
5001 public:
5002     /// <summary>
5003     ///     Sends a progress report to the asynchronous action or operation to which this progress reporter is bound.
5004     /// </summary>
5005     /// <param name="_Val">
5006     ///     The payload to report through a progress notification.
5007     /// </param>
5008     /**/
5009     void report(const _ProgressType& _Val) const { _M_dispatcher->_Report(_Val); }
5010 
5011     template<typename _ClassPtrType>
5012     static progress_reporter _CreateReporter(_ClassPtrType _Ptr)
5013     {
5014         progress_reporter _Reporter;
5015         details::_ProgressDispatcherBase<_ProgressType>* _PDispatcher =
5016             new details::_ProgressDispatcher<_ProgressType, _ClassPtrType>(_Ptr);
5017         _Reporter._M_dispatcher = _PtrType(_PDispatcher);
5018         return _Reporter;
5019     }
5020     progress_reporter() {}
5021 
5022 private:
5023     progress_reporter(details::_ProgressReporterCtorArgType);
5024 
5025     _PtrType _M_dispatcher;
5026 };
5027 
5028 namespace details
5029 {
5030 //
5031 // maps internal definitions for AsyncStatus and defines states that are not client visible
5032 //
5033 enum _AsyncStatusInternal
5034 {
5035     _AsyncCreated = -1, // externally invisible
5036     // client visible states (must match AsyncStatus exactly)
5037     _AsyncStarted = 0,   // Windows::Foundation::AsyncStatus::Started,
5038     _AsyncCompleted = 1, // Windows::Foundation::AsyncStatus::Completed,
5039     _AsyncCanceled = 2,  // Windows::Foundation::AsyncStatus::Canceled,
5040     _AsyncError = 3,     // Windows::Foundation::AsyncStatus::Error,
5041     // non-client visible internal states
5042     _AsyncCancelPending,
5043     _AsyncClosed,
5044     _AsyncUndefined
5045 };
5046 
5047 //
5048 // designates whether the "GetResults" method returns a single result (after complete fires) or multiple results
5049 // (which are progressively consumable between Start state and before Close is called)
5050 //
5051 enum _AsyncResultType
5052 {
5053     SingleResult = 0x0001,
5054     MultipleResults = 0x0002
5055 };
5056 
5057 // ***************************************************************************
5058 // Template type traits and helpers for async production APIs:
5059 //
5060 
5061 struct _ZeroArgumentFunctor
5062 {
5063 };
5064 struct _OneArgumentFunctor
5065 {
5066 };
5067 struct _TwoArgumentFunctor
5068 {
5069 };
5070 
5071 // ****************************************
5072 // CLASS TYPES:
5073 
5074 // ********************
5075 // TWO ARGUMENTS:
5076 
5077 // non-void arg:
5078 template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
5079 _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
5080 
5081 // non-void arg:
5082 template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
5083 _Arg2 _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
5084 
5085 template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
5086 _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
5087 
5088 template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
5089 _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
5090 
5091 // ********************
5092 // ONE ARGUMENT:
5093 
5094 // non-void arg:
5095 template<typename _Class, typename _ReturnType, typename _Arg1>
5096 _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
5097 
5098 // non-void arg:
5099 template<typename _Class, typename _ReturnType, typename _Arg1>
5100 void _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
5101 
5102 template<typename _Class, typename _ReturnType, typename _Arg1>
5103 _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
5104 
5105 template<typename _Class, typename _ReturnType, typename _Arg1>
5106 _OneArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1) const);
5107 
5108 // ********************
5109 // ZERO ARGUMENT:
5110 
5111 // void arg:
5112 template<typename _Class, typename _ReturnType>
5113 void _Arg1ClassHelperThunk(_ReturnType (_Class::*)() const);
5114 
5115 // void arg:
5116 template<typename _Class, typename _ReturnType>
5117 void _Arg2ClassHelperThunk(_ReturnType (_Class::*)() const);
5118 
5119 // void arg:
5120 template<typename _Class, typename _ReturnType>
5121 _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)() const);
5122 
5123 template<typename _Class, typename _ReturnType>
5124 _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)() const);
5125 
5126 // ****************************************
5127 // POINTER TYPES:
5128 
5129 // ********************
5130 // TWO ARGUMENTS:
5131 
5132 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5133 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl*)(_Arg1, _Arg2));
5134 
5135 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5136 _Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl*)(_Arg1, _Arg2));
5137 
5138 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5139 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl*)(_Arg1, _Arg2));
5140 
5141 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5142 _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl*)(_Arg1, _Arg2));
5143 
5144 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5145 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall*)(_Arg1, _Arg2));
5146 
5147 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5148 _Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall*)(_Arg1, _Arg2));
5149 
5150 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5151 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall*)(_Arg1, _Arg2));
5152 
5153 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5154 _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall*)(_Arg1, _Arg2));
5155 
5156 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5157 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall*)(_Arg1, _Arg2));
5158 
5159 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5160 _Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall*)(_Arg1, _Arg2));
5161 
5162 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5163 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall*)(_Arg1, _Arg2));
5164 
5165 template<typename _ReturnType, typename _Arg1, typename _Arg2>
5166 _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall*)(_Arg1, _Arg2));
5167 
5168 // ********************
5169 // ONE ARGUMENT:
5170 
5171 template<typename _ReturnType, typename _Arg1>
5172 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl*)(_Arg1));
5173 
5174 template<typename _ReturnType, typename _Arg1>
5175 void _Arg2PFNHelperThunk(_ReturnType(__cdecl*)(_Arg1));
5176 
5177 template<typename _ReturnType, typename _Arg1>
5178 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl*)(_Arg1));
5179 
5180 template<typename _ReturnType, typename _Arg1>
5181 _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl*)(_Arg1));
5182 
5183 template<typename _ReturnType, typename _Arg1>
5184 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall*)(_Arg1));
5185 
5186 template<typename _ReturnType, typename _Arg1>
5187 void _Arg2PFNHelperThunk(_ReturnType(__stdcall*)(_Arg1));
5188 
5189 template<typename _ReturnType, typename _Arg1>
5190 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall*)(_Arg1));
5191 
5192 template<typename _ReturnType, typename _Arg1>
5193 _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall*)(_Arg1));
5194 
5195 template<typename _ReturnType, typename _Arg1>
5196 _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall*)(_Arg1));
5197 
5198 template<typename _ReturnType, typename _Arg1>
5199 void _Arg2PFNHelperThunk(_ReturnType(__fastcall*)(_Arg1));
5200 
5201 template<typename _ReturnType, typename _Arg1>
5202 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall*)(_Arg1));
5203 
5204 template<typename _ReturnType, typename _Arg1>
5205 _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall*)(_Arg1));
5206 
5207 // ********************
5208 // ZERO ARGUMENT:
5209 
5210 template<typename _ReturnType>
5211 void _Arg1PFNHelperThunk(_ReturnType(__cdecl*)());
5212 
5213 template<typename _ReturnType>
5214 void _Arg2PFNHelperThunk(_ReturnType(__cdecl*)());
5215 
5216 template<typename _ReturnType>
5217 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl*)());
5218 
5219 template<typename _ReturnType>
5220 _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl*)());
5221 
5222 template<typename _ReturnType>
5223 void _Arg1PFNHelperThunk(_ReturnType(__stdcall*)());
5224 
5225 template<typename _ReturnType>
5226 void _Arg2PFNHelperThunk(_ReturnType(__stdcall*)());
5227 
5228 template<typename _ReturnType>
5229 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall*)());
5230 
5231 template<typename _ReturnType>
5232 _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall*)());
5233 
5234 template<typename _ReturnType>
5235 void _Arg1PFNHelperThunk(_ReturnType(__fastcall*)());
5236 
5237 template<typename _ReturnType>
5238 void _Arg2PFNHelperThunk(_ReturnType(__fastcall*)());
5239 
5240 template<typename _ReturnType>
5241 _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall*)());
5242 
5243 template<typename _ReturnType>
5244 _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall*)());
5245 
5246 template<typename _T>
5247 struct _FunctorArguments
5248 {
5249     static const size_t _Count = 0;
5250 };
5251 
5252 template<>
5253 struct _FunctorArguments<_OneArgumentFunctor>
5254 {
5255     static const size_t _Count = 1;
5256 };
5257 
5258 template<>
5259 struct _FunctorArguments<_TwoArgumentFunctor>
5260 {
5261     static const size_t _Count = 2;
5262 };
5263 
5264 template<typename _T>
5265 struct _FunctorTypeTraits
5266 {
5267     typedef decltype(_ArgumentCountHelper(&(_T::operator()))) _ArgumentCountType;
5268     static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
5269 
5270     typedef decltype(_ReturnTypeClassHelperThunk(&(_T::operator()))) _ReturnType;
5271     typedef decltype(_Arg1ClassHelperThunk(&(_T::operator()))) _Argument1Type;
5272     typedef decltype(_Arg2ClassHelperThunk(&(_T::operator()))) _Argument2Type;
5273 };
5274 
5275 template<typename _T>
5276 struct _FunctorTypeTraits<_T*>
5277 {
5278     typedef decltype(_ArgumentCountHelper(stdx::declval<_T*>())) _ArgumentCountType;
5279     static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
5280 
5281     typedef decltype(_ReturnTypePFNHelperThunk(stdx::declval<_T*>())) _ReturnType;
5282     typedef decltype(_Arg1PFNHelperThunk(stdx::declval<_T*>())) _Argument1Type;
5283     typedef decltype(_Arg2PFNHelperThunk(stdx::declval<_T*>())) _Argument2Type;
5284 };
5285 
5286 template<typename _T>
5287 struct _ProgressTypeTraits
5288 {
5289     static const bool _TakesProgress = false;
5290     typedef void _ProgressType;
5291 };
5292 
5293 template<typename _T>
5294 struct _ProgressTypeTraits<progress_reporter<_T>>
5295 {
5296     static const bool _TakesProgress = true;
5297     typedef typename _T _ProgressType;
5298 };
5299 
5300 template<typename _T, size_t count = _FunctorTypeTraits<_T>::_ArgumentCount>
5301 struct _CAFunctorOptions
5302 {
5303     static const bool _TakesProgress = false;
5304     static const bool _TakesToken = false;
5305     typedef void _ProgressType;
5306 };
5307 
5308 template<typename _T>
5309 struct _CAFunctorOptions<_T, 1>
5310 {
5311 private:
5312     typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
5313 
5314 public:
5315     static const bool _TakesProgress = _ProgressTypeTraits<_Argument1Type>::_TakesProgress;
5316     static const bool _TakesToken = !_TakesProgress;
5317     typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
5318 };
5319 
5320 template<typename _T>
5321 struct _CAFunctorOptions<_T, 2>
5322 {
5323 private:
5324     typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
5325 
5326 public:
5327     static const bool _TakesProgress = true;
5328     static const bool _TakesToken = true;
5329     typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
5330 };
5331 
5332 ref class _Zip
5333 {
5334 };
5335 
5336 // ***************************************************************************
5337 // Async Operation Task Generators
5338 //
5339 
5340 //
5341 // Functor returns an IAsyncInfo - result needs to be wrapped in a task:
5342 //
5343 template<typename _AsyncSelector, typename _ReturnType>
5344 struct _SelectorTaskGenerator
5345 {
5346     template<typename _Function>
5347     static task<_ReturnType> _GenerateTask_0(const _Function& _Func,
5348                                              cancellation_token_source _Cts,
5349                                              const _TaskCreationCallstack& _callstack)
5350     {
5351         task_options _taskOptinos(_Cts.get_token());
5352         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5353         return task<_ReturnType>(_Func(), _taskOptinos);
5354     }
5355 
5356     template<typename _Function>
5357     static task<_ReturnType> _GenerateTask_1C(const _Function& _Func,
5358                                               cancellation_token_source _Cts,
5359                                               const _TaskCreationCallstack& _callstack)
5360     {
5361         task_options _taskOptinos(_Cts.get_token());
5362         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5363         return task<_ReturnType>(_Func(_Cts.get_token()), _taskOptinos);
5364     }
5365 
5366     template<typename _Function, typename _ProgressObject>
5367     static task<_ReturnType> _GenerateTask_1P(const _Function& _Func,
5368                                               const _ProgressObject& _Progress,
5369                                               cancellation_token_source _Cts,
5370                                               const _TaskCreationCallstack& _callstack)
5371     {
5372         task_options _taskOptinos(_Cts.get_token());
5373         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5374         return task<_ReturnType>(_Func(_Progress), _taskOptinos);
5375     }
5376 
5377     template<typename _Function, typename _ProgressObject>
5378     static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func,
5379                                                const _ProgressObject& _Progress,
5380                                                cancellation_token_source _Cts,
5381                                                const _TaskCreationCallstack& _callstack)
5382     {
5383         task_options _taskOptinos(_Cts.get_token());
5384         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5385         return task<_ReturnType>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
5386     }
5387 };
5388 
5389 template<typename _AsyncSelector>
5390 struct _SelectorTaskGenerator<_AsyncSelector, void>
5391 {
5392     template<typename _Function>
5393     static task<void> _GenerateTask_0(const _Function& _Func,
5394                                       cancellation_token_source _Cts,
5395                                       const _TaskCreationCallstack& _callstack)
5396     {
5397         task_options _taskOptinos(_Cts.get_token());
5398         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5399         return task<void>(_Func(), _taskOptinos);
5400     }
5401 
5402     template<typename _Function>
5403     static task<void> _GenerateTask_1C(const _Function& _Func,
5404                                        cancellation_token_source _Cts,
5405                                        const _TaskCreationCallstack& _callstack)
5406     {
5407         task_options _taskOptinos(_Cts.get_token());
5408         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5409         return task<void>(_Func(_Cts.get_token()), _taskOptinos);
5410     }
5411 
5412     template<typename _Function, typename _ProgressObject>
5413     static task<void> _GenerateTask_1P(const _Function& _Func,
5414                                        const _ProgressObject& _Progress,
5415                                        cancellation_token_source _Cts,
5416                                        const _TaskCreationCallstack& _callstack)
5417     {
5418         task_options _taskOptinos(_Cts.get_token());
5419         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5420         return task<void>(_Func(_Progress), _taskOptinos);
5421     }
5422 
5423     template<typename _Function, typename _ProgressObject>
5424     static task<void> _GenerateTask_2PC(const _Function& _Func,
5425                                         const _ProgressObject& _Progress,
5426                                         cancellation_token_source _Cts,
5427                                         const _TaskCreationCallstack& _callstack)
5428     {
5429         task_options _taskOptinos(_Cts.get_token());
5430         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5431         return task<void>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
5432     }
5433 };
5434 
5435 //
5436 // Functor returns a result - it needs to be wrapped in a task:
5437 //
5438 template<typename _ReturnType>
5439 struct _SelectorTaskGenerator<_TypeSelectorNoAsync, _ReturnType>
5440 {
5441 
5442 #pragma warning(push)
5443 #pragma warning(disable : 4702)
5444     template<typename _Function>
5445     static task<_ReturnType> _GenerateTask_0(const _Function& _Func,
5446                                              cancellation_token_source _Cts,
5447                                              const _TaskCreationCallstack& _callstack)
5448     {
5449         task_options _taskOptinos(_Cts.get_token());
5450         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5451         return task<_ReturnType>(
5452             [=]() -> _ReturnType {
5453                 _Task_generator_oversubscriber_t _Oversubscriber;
5454                 (_Oversubscriber);
5455                 return _Func();
5456             },
5457             _taskOptinos);
5458     }
5459 #pragma warning(pop)
5460 
5461     template<typename _Function>
5462     static task<_ReturnType> _GenerateTask_1C(const _Function& _Func,
5463                                               cancellation_token_source _Cts,
5464                                               const _TaskCreationCallstack& _callstack)
5465     {
5466         task_options _taskOptinos(_Cts.get_token());
5467         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5468         return task<_ReturnType>(
5469             [=]() -> _ReturnType {
5470                 _Task_generator_oversubscriber_t _Oversubscriber;
5471                 (_Oversubscriber);
5472                 return _Func(_Cts.get_token());
5473             },
5474             _taskOptinos);
5475     }
5476 
5477     template<typename _Function, typename _ProgressObject>
5478     static task<_ReturnType> _GenerateTask_1P(const _Function& _Func,
5479                                               const _ProgressObject& _Progress,
5480                                               cancellation_token_source _Cts,
5481                                               const _TaskCreationCallstack& _callstack)
5482     {
5483         task_options _taskOptinos(_Cts.get_token());
5484         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5485         return task<_ReturnType>(
5486             [=]() -> _ReturnType {
5487                 _Task_generator_oversubscriber_t _Oversubscriber;
5488                 (_Oversubscriber);
5489                 return _Func(_Progress);
5490             },
5491             _taskOptinos);
5492     }
5493 
5494     template<typename _Function, typename _ProgressObject>
5495     static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func,
5496                                                const _ProgressObject& _Progress,
5497                                                cancellation_token_source _Cts,
5498                                                const _TaskCreationCallstack& _callstack)
5499     {
5500         task_options _taskOptinos(_Cts.get_token());
5501         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5502         return task<_ReturnType>(
5503             [=]() -> _ReturnType {
5504                 _Task_generator_oversubscriber_t _Oversubscriber;
5505                 (_Oversubscriber);
5506                 return _Func(_Progress, _Cts.get_token());
5507             },
5508             _taskOptinos);
5509     }
5510 };
5511 
5512 template<>
5513 struct _SelectorTaskGenerator<_TypeSelectorNoAsync, void>
5514 {
5515     template<typename _Function>
5516     static task<void> _GenerateTask_0(const _Function& _Func,
5517                                       cancellation_token_source _Cts,
5518                                       const _TaskCreationCallstack& _callstack)
5519     {
5520         task_options _taskOptinos(_Cts.get_token());
5521         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5522         return task<void>(
5523             [=]() {
5524                 _Task_generator_oversubscriber_t _Oversubscriber;
5525                 (_Oversubscriber);
5526                 _Func();
5527             },
5528             _taskOptinos);
5529     }
5530 
5531     template<typename _Function>
5532     static task<void> _GenerateTask_1C(const _Function& _Func,
5533                                        cancellation_token_source _Cts,
5534                                        const _TaskCreationCallstack& _callstack)
5535     {
5536         task_options _taskOptinos(_Cts.get_token());
5537         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5538         return task<void>(
5539             [=]() {
5540                 _Task_generator_oversubscriber_t _Oversubscriber;
5541                 (_Oversubscriber);
5542                 _Func(_Cts.get_token());
5543             },
5544             _taskOptinos);
5545     }
5546 
5547     template<typename _Function, typename _ProgressObject>
5548     static task<void> _GenerateTask_1P(const _Function& _Func,
5549                                        const _ProgressObject& _Progress,
5550                                        cancellation_token_source _Cts,
5551                                        const _TaskCreationCallstack& _callstack)
5552     {
5553         task_options _taskOptinos(_Cts.get_token());
5554         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5555         return task<void>(
5556             [=]() {
5557                 _Task_generator_oversubscriber_t _Oversubscriber;
5558                 (_Oversubscriber);
5559                 _Func(_Progress);
5560             },
5561             _taskOptinos);
5562     }
5563 
5564     template<typename _Function, typename _ProgressObject>
5565     static task<void> _GenerateTask_2PC(const _Function& _Func,
5566                                         const _ProgressObject& _Progress,
5567                                         cancellation_token_source _Cts,
5568                                         const _TaskCreationCallstack& _callstack)
5569     {
5570         task_options _taskOptinos(_Cts.get_token());
5571         details::_get_internal_task_options(_taskOptinos)._set_creation_callstack(_callstack);
5572         return task<void>(
5573             [=]() {
5574                 _Task_generator_oversubscriber_t _Oversubscriber;
5575                 (_Oversubscriber);
5576                 _Func(_Progress, _Cts.get_token());
5577             },
5578             _taskOptinos);
5579     }
5580 };
5581 
5582 //
5583 // Functor returns a task - the task can directly be returned:
5584 //
5585 template<typename _ReturnType>
5586 struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, _ReturnType>
5587 {
5588     template<typename _Function>
5589     static task<_ReturnType> _GenerateTask_0(const _Function& _Func,
5590                                              cancellation_token_source _Cts,
5591                                              const _TaskCreationCallstack& _callstack)
5592     {
5593         return _Func();
5594     }
5595 
5596     template<typename _Function>
5597     static task<_ReturnType> _GenerateTask_1C(const _Function& _Func,
5598                                               cancellation_token_source _Cts,
5599                                               const _TaskCreationCallstack& _callstack)
5600     {
5601         return _Func(_Cts.get_token());
5602     }
5603 
5604     template<typename _Function, typename _ProgressObject>
5605     static task<_ReturnType> _GenerateTask_1P(const _Function& _Func,
5606                                               const _ProgressObject& _Progress,
5607                                               cancellation_token_source _Cts,
5608                                               const _TaskCreationCallstack& _callstack)
5609     {
5610         return _Func(_Progress);
5611     }
5612 
5613     template<typename _Function, typename _ProgressObject>
5614     static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func,
5615                                                const _ProgressObject& _Progress,
5616                                                cancellation_token_source _Cts,
5617                                                const _TaskCreationCallstack& _callstack)
5618     {
5619         return _Func(_Progress, _Cts.get_token());
5620     }
5621 };
5622 
5623 template<>
5624 struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, void>
5625 {
5626     template<typename _Function>
5627     static task<void> _GenerateTask_0(const _Function& _Func,
5628                                       cancellation_token_source _Cts,
5629                                       const _TaskCreationCallstack& _callstack)
5630     {
5631         return _Func();
5632     }
5633 
5634     template<typename _Function>
5635     static task<void> _GenerateTask_1C(const _Function& _Func,
5636                                        cancellation_token_source _Cts,
5637                                        const _TaskCreationCallstack& _callstack)
5638     {
5639         return _Func(_Cts.get_token());
5640     }
5641 
5642     template<typename _Function, typename _ProgressObject>
5643     static task<void> _GenerateTask_1P(const _Function& _Func,
5644                                        const _ProgressObject& _Progress,
5645                                        cancellation_token_source _Cts,
5646                                        const _TaskCreationCallstack& _callstack)
5647     {
5648         return _Func(_Progress);
5649     }
5650 
5651     template<typename _Function, typename _ProgressObject>
5652     static task<void> _GenerateTask_2PC(const _Function& _Func,
5653                                         const _ProgressObject& _Progress,
5654                                         cancellation_token_source _Cts,
5655                                         const _TaskCreationCallstack& _callstack)
5656     {
5657         return _Func(_Progress, _Cts.get_token());
5658     }
5659 };
5660 
5661 template<typename _Generator, bool _TakesToken, bool TakesProgress>
5662 struct _TaskGenerator
5663 {
5664 };
5665 
5666 template<typename _Generator>
5667 struct _TaskGenerator<_Generator, false, false>
5668 {
5669     template<typename _Function, typename _ClassPtr, typename _ProgressType>
5670     static auto _GenerateTask(const _Function& _Func,
5671                               _ClassPtr _Ptr,
5672                               cancellation_token_source _Cts,
5673                               const _TaskCreationCallstack& _callstack)
5674         -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5675     {
5676         return _Generator::_GenerateTask_0(_Func, _Cts, _callstack);
5677     }
5678 };
5679 
5680 template<typename _Generator>
5681 struct _TaskGenerator<_Generator, true, false>
5682 {
5683     template<typename _Function, typename _ClassPtr, typename _ProgressType>
5684     static auto _GenerateTask(const _Function& _Func,
5685                               _ClassPtr _Ptr,
5686                               cancellation_token_source _Cts,
5687                               const _TaskCreationCallstack& _callstack)
5688         -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5689     {
5690         return _Generator::_GenerateTask_1C(_Func, _Cts, _callstack);
5691     }
5692 };
5693 
5694 template<typename _Generator>
5695 struct _TaskGenerator<_Generator, false, true>
5696 {
5697     template<typename _Function, typename _ClassPtr, typename _ProgressType>
5698     static auto _GenerateTask(const _Function& _Func,
5699                               _ClassPtr _Ptr,
5700                               cancellation_token_source _Cts,
5701                               const _TaskCreationCallstack& _callstack)
5702         -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5703     {
5704         return _Generator::_GenerateTask_1P(
5705             _Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5706     }
5707 };
5708 
5709 template<typename _Generator>
5710 struct _TaskGenerator<_Generator, true, true>
5711 {
5712     template<typename _Function, typename _ClassPtr, typename _ProgressType>
5713     static auto _GenerateTask(const _Function& _Func,
5714                               _ClassPtr _Ptr,
5715                               cancellation_token_source _Cts,
5716                               const _TaskCreationCallstack& _callstack)
5717         -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5718     {
5719         return _Generator::_GenerateTask_2PC(
5720             _Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5721     }
5722 };
5723 
5724 // ***************************************************************************
5725 // Async Operation Attributes Classes
5726 //
5727 // These classes are passed through the hierarchy of async base classes in order to hold multiple attributes of a given
5728 // async construct in a single container. An attribute class must define:
5729 //
5730 // Mandatory:
5731 // -------------------------
5732 //
5733 // _AsyncBaseType           : The Windows Runtime interface which is being implemented.
5734 // _CompletionDelegateType  : The Windows Runtime completion delegate type for the interface.
5735 // _ProgressDelegateType    : If _TakesProgress is true, the Windows Runtime progress delegate type for the interface.
5736 // If it is false, an empty Windows Runtime type. _ReturnType              : The return type of the async construct
5737 // (void for actions / non-void for operations)
5738 //
5739 // _TakesProgress           : An indication as to whether or not
5740 //
5741 // _Generate_Task           : A function adapting the user's function into what's necessary to produce the appropriate
5742 // task
5743 //
5744 // Optional:
5745 // -------------------------
5746 //
5747 
5748 template<typename _Function,
5749          typename _ProgressType,
5750          typename _ReturnType,
5751          typename _TaskTraits,
5752          bool _TakesToken,
5753          bool _TakesProgress>
5754 struct _AsyncAttributes
5755 {
5756 };
5757 
5758 template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5759 struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, true>
5760 {
5761     typedef typename Windows::Foundation::IAsyncOperationWithProgress<_ReturnType, _ProgressType> _AsyncBaseType;
5762     typedef typename Windows::Foundation::AsyncOperationProgressHandler<_ReturnType, _ProgressType>
5763         _ProgressDelegateType;
5764     typedef typename Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_ReturnType, _ProgressType>
5765         _CompletionDelegateType;
5766     typedef typename _ReturnType _ReturnType;
5767     typedef typename _ProgressType _ProgressType;
5768     typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5769     typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5770     typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5771 
5772     static const bool _TakesProgress = true;
5773     static const bool _TakesToken = _TakesToken;
5774 
5775     template<typename _Function, typename _ClassPtr>
5776     static task<_ReturnType> _Generate_Task(const _Function& _Func,
5777                                             _ClassPtr _Ptr,
5778                                             cancellation_token_source _Cts,
5779                                             const _TaskCreationCallstack& _callstack)
5780     {
5781         return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5782     }
5783 };
5784 
5785 template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5786 struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, false>
5787 {
5788     typedef typename Windows::Foundation::IAsyncOperation<_ReturnType> _AsyncBaseType;
5789     typedef _Zip _ProgressDelegateType;
5790     typedef typename Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType> _CompletionDelegateType;
5791     typedef typename _ReturnType _ReturnType;
5792     typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5793     typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5794     typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5795 
5796     static const bool _TakesProgress = false;
5797     static const bool _TakesToken = _TakesToken;
5798 
5799     template<typename _Function, typename _ClassPtr>
5800     static task<_ReturnType> _Generate_Task(const _Function& _Func,
5801                                             _ClassPtr _Ptr,
5802                                             cancellation_token_source _Cts,
5803                                             const _TaskCreationCallstack& _callstack)
5804     {
5805         return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5806     }
5807 };
5808 
5809 template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5810 struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, true>
5811 {
5812     typedef typename Windows::Foundation::IAsyncActionWithProgress<_ProgressType> _AsyncBaseType;
5813     typedef typename Windows::Foundation::AsyncActionProgressHandler<_ProgressType> _ProgressDelegateType;
5814     typedef typename Windows::Foundation::AsyncActionWithProgressCompletedHandler<_ProgressType>
5815         _CompletionDelegateType;
5816     typedef void _ReturnType;
5817     typedef typename _ProgressType _ProgressType;
5818     typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5819     typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5820     typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5821 
5822     static const bool _TakesProgress = true;
5823     static const bool _TakesToken = _TakesToken;
5824 
5825     template<typename _Function, typename _ClassPtr>
5826     static task<_ReturnType> _Generate_Task(const _Function& _Func,
5827                                             _ClassPtr _Ptr,
5828                                             cancellation_token_source _Cts,
5829                                             const _TaskCreationCallstack& _callstack)
5830     {
5831         return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5832     }
5833 };
5834 
5835 template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5836 struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, false>
5837 {
5838     typedef typename Windows::Foundation::IAsyncAction _AsyncBaseType;
5839     typedef _Zip _ProgressDelegateType;
5840     typedef typename Windows::Foundation::AsyncActionCompletedHandler _CompletionDelegateType;
5841     typedef void _ReturnType;
5842     typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5843     typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5844     typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5845 
5846     static const bool _TakesProgress = false;
5847     static const bool _TakesToken = _TakesToken;
5848 
5849     template<typename _Function, typename _ClassPtr>
5850     static task<_ReturnType> _Generate_Task(const _Function& _Func,
5851                                             _ClassPtr _Ptr,
5852                                             cancellation_token_source _Cts,
5853                                             const _TaskCreationCallstack& _callstack)
5854     {
5855         return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5856     }
5857 };
5858 
5859 template<typename _Function>
5860 struct _AsyncLambdaTypeTraits
5861 {
5862     typedef typename _FunctorTypeTraits<_Function>::_ReturnType _ReturnType;
5863     typedef typename _FunctorTypeTraits<_Function>::_Argument1Type _Argument1Type;
5864     typedef typename _CAFunctorOptions<_Function>::_ProgressType _ProgressType;
5865 
5866     static const bool _TakesProgress = _CAFunctorOptions<_Function>::_TakesProgress;
5867     static const bool _TakesToken = _CAFunctorOptions<_Function>::_TakesToken;
5868 
5869     typedef typename _TaskTypeTraits<_ReturnType> _TaskTraits;
5870     typedef typename _AsyncAttributes<_Function,
5871                                       _ProgressType,
5872                                       typename _TaskTraits::_TaskRetType,
5873                                       _TaskTraits,
5874                                       _TakesToken,
5875                                       _TakesProgress>
5876         _AsyncAttributes;
5877 };
5878 
5879 // ***************************************************************************
5880 // AsyncInfo (and completion) Layer:
5881 //
5882 
5883 //
5884 // Internal base class implementation for async operations (based on internal Windows representation for ABI level async
5885 // operations)
5886 //
5887 template<typename _Attributes, _AsyncResultType resultType = SingleResult>
5888 ref class _AsyncInfoBase abstract : _Attributes::_AsyncBaseType
5889 {
5890     internal :
5891 
5892         _AsyncInfoBase()
5893         : _M_currentStatus(_AsyncStatusInternal::_AsyncCreated)
5894         , _M_errorCode(S_OK)
5895         , _M_completeDelegate(nullptr)
5896         , _M_CompleteDelegateAssigned(0)
5897         , _M_CallbackMade(0)
5898     {
5899         _M_id = ::pplx::details::platform::GetNextAsyncId();
5900     }
5901 
5902 public:
5903     virtual typename _Attributes::_ReturnType GetResults()
5904     {
5905         throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5906     }
5907 
5908     virtual property unsigned int Id
5909     {
5910         unsigned int get()
5911         {
5912             _CheckValidStateForAsyncInfoCall();
5913 
5914             return _M_id;
5915         }
5916 
5917         void set(unsigned int id)
5918         {
5919             _CheckValidStateForAsyncInfoCall();
5920 
5921             if (id == 0)
5922             {
5923                 throw ::Platform::Exception::CreateException(E_INVALIDARG);
5924             }
5925             else if (_M_currentStatus != _AsyncStatusInternal::_AsyncCreated)
5926             {
5927                 throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5928             }
5929 
5930             _M_id = id;
5931         }
5932     }
5933 
5934     virtual property Windows::Foundation::AsyncStatus Status
5935     {
5936         Windows::Foundation::AsyncStatus get()
5937         {
5938             _CheckValidStateForAsyncInfoCall();
5939 
5940             _AsyncStatusInternal _Current = _M_currentStatus;
5941 
5942             //
5943             // Map our internal cancel pending to canceled. This way "pending canceled" looks to the outside as
5944             // "canceled" but can still transition to "completed" if the operation completes without acknowledging the
5945             // cancellation request
5946             //
5947             switch (_Current)
5948             {
5949                 case _AsyncCancelPending: _Current = _AsyncCanceled; break;
5950                 case _AsyncCreated: _Current = _AsyncStarted; break;
5951                 default: break;
5952             }
5953 
5954             return static_cast<Windows::Foundation::AsyncStatus>(_Current);
5955         }
5956     }
5957 
5958     virtual property Windows::Foundation::HResult ErrorCode
5959     {
5960         Windows::Foundation::HResult get()
5961         {
5962             _CheckValidStateForAsyncInfoCall();
5963 
5964             Windows::Foundation::HResult _Hr;
5965             _Hr.Value = _M_errorCode;
5966             return _Hr;
5967         }
5968     }
5969 
5970     virtual property typename _Attributes::_ProgressDelegateType ^
5971         Progress {
5972             typename typename _Attributes::_ProgressDelegateType ^ get() { return _GetOnProgress(); }
5973 
5974                 void set(typename _Attributes::_ProgressDelegateType ^ _ProgressHandler)
5975             {
5976                 _PutOnProgress(_ProgressHandler);
5977             }
5978         }
5979 
5980         virtual void
5981         Cancel()
5982     {
5983         if (_TransitionToState(_AsyncCancelPending))
5984         {
5985             _OnCancel();
5986         }
5987     }
5988 
5989     virtual void Close()
5990     {
5991         if (_TransitionToState(_AsyncClosed))
5992         {
5993             _OnClose();
5994         }
5995         else
5996         {
5997             if (_M_currentStatus != _AsyncClosed) // Closed => Closed transition is just ignored
5998             {
5999                 throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
6000             }
6001         }
6002     }
6003 
6004     virtual property typename _Attributes::_CompletionDelegateType ^
6005         Completed {
6006             typename _Attributes::_CompletionDelegateType ^
6007                 get() {
6008                     _CheckValidStateForDelegateCall();
6009                     return _M_completeDelegate;
6010                 }
6011 
6012                 void set(typename _Attributes::_CompletionDelegateType ^ _CompleteHandler)
6013             {
6014                 _CheckValidStateForDelegateCall();
6015                 // this delegate property is "write once"
6016                 if (InterlockedIncrement(&_M_CompleteDelegateAssigned) == 1)
6017                 {
6018                     _M_completeDelegateContext = _ContextCallback::_CaptureCurrent();
6019                     _M_completeDelegate = _CompleteHandler;
6020                     // Guarantee that the write of _M_completeDelegate is ordered with respect to the read of state
6021                     // below as perceived from _FireCompletion on another thread.
6022                     MemoryBarrier();
6023                     if (_IsTerminalState())
6024                     {
6025                         _FireCompletion();
6026                     }
6027                 }
6028                 else
6029                 {
6030                     throw ::Platform::Exception::CreateException(E_ILLEGAL_DELEGATE_ASSIGNMENT);
6031                 }
6032             }
6033         }
6034 
6035         protected private :
6036 
6037         // _Start - this is not externally visible since async operations "hot start" before returning to the caller
6038         void
6039         _Start()
6040     {
6041         if (_TransitionToState(_AsyncStarted))
6042         {
6043             _OnStart();
6044         }
6045         else
6046         {
6047             throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
6048         }
6049     }
6050 
6051     void _FireCompletion()
6052     {
6053         _TryTransitionToCompleted();
6054 
6055         // we guarantee that completion can only ever be fired once
6056         if (_M_completeDelegate != nullptr && InterlockedIncrement(&_M_CallbackMade) == 1)
6057         {
6058             _M_completeDelegateContext._CallInContext([=] {
6059                 _M_completeDelegate((_Attributes::_AsyncBaseType ^) this, this->Status);
6060                 _M_completeDelegate = nullptr;
6061             });
6062         }
6063     }
6064 
6065     virtual typename _Attributes::_ProgressDelegateType ^
6066         _GetOnProgress() { throw ::Platform::Exception::CreateException(E_UNEXPECTED); }
6067 
6068         virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType ^ _ProgressHandler)
6069     {
6070         throw ::Platform::Exception::CreateException(E_UNEXPECTED);
6071     }
6072 
6073     bool _TryTransitionToCompleted() { return _TransitionToState(_AsyncStatusInternal::_AsyncCompleted); }
6074 
6075     bool _TryTransitionToCancelled() { return _TransitionToState(_AsyncStatusInternal::_AsyncCanceled); }
6076 
6077     bool _TryTransitionToError(const HRESULT error)
6078     {
6079         _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_errorCode), error, S_OK);
6080         return _TransitionToState(_AsyncStatusInternal::_AsyncError);
6081     }
6082 
6083     // This method checks to see if the delegate properties can be
6084     // modified in the current state and generates the appropriate
6085     // error hr in the case of violation.
6086     inline void _CheckValidStateForDelegateCall()
6087     {
6088         if (_M_currentStatus == _AsyncClosed)
6089         {
6090             throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
6091         }
6092     }
6093 
6094     // This method checks to see if results can be collected in the
6095     // current state and generates the appropriate error hr in
6096     // the case of a violation.
6097     inline void _CheckValidStateForResultsCall()
6098     {
6099         _AsyncStatusInternal _Current = _M_currentStatus;
6100 
6101         if (_Current == _AsyncError)
6102         {
6103             throw ::Platform::Exception::CreateException(_M_errorCode);
6104         }
6105 #pragma warning(push)
6106 #pragma warning(disable : 4127) // Conditional expression is constant
6107         // single result illegal before transition to Completed or Cancelled state
6108         if (resultType == SingleResult)
6109 #pragma warning(pop)
6110         {
6111             if (_Current != _AsyncCompleted)
6112             {
6113                 throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
6114             }
6115         }
6116         // multiple results can be called after Start has been called and before/after Completed
6117         else if (_Current != _AsyncStarted && _Current != _AsyncCancelPending && _Current != _AsyncCanceled &&
6118                  _Current != _AsyncCompleted)
6119         {
6120             throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
6121         }
6122     }
6123 
6124     // This method can be called by derived classes periodically to determine
6125     // whether the asynchronous operation should continue processing or should
6126     // be halted.
6127     inline bool _ContinueAsyncOperation() { return (_M_currentStatus == _AsyncStarted); }
6128 
6129     // These two methods are used to allow the async worker implementation do work on
6130     // state transitions. No real "work" should be done in these methods. In other words
6131     // they should not block for a long time on UI timescales.
6132     virtual void _OnStart() = 0;
6133     virtual void _OnClose() = 0;
6134     virtual void _OnCancel() = 0;
6135 
6136 private:
6137     // This method is used to check if calls to the AsyncInfo properties
6138     // (id, status, errorcode) are legal in the current state. It also
6139     // generates the appropriate error hr to return in the case of an
6140     // illegal call.
6141     inline void _CheckValidStateForAsyncInfoCall()
6142     {
6143         _AsyncStatusInternal _Current = _M_currentStatus;
6144         if (_Current == _AsyncClosed)
6145         {
6146             throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
6147         }
6148         else if (_Current == _AsyncCreated)
6149         {
6150             throw ::Platform::Exception::CreateException(E_ASYNC_OPERATION_NOT_STARTED);
6151         }
6152     }
6153 
6154     inline bool _TransitionToState(const _AsyncStatusInternal _NewState)
6155     {
6156         _AsyncStatusInternal _Current = _M_currentStatus;
6157 
6158         // This enforces the valid state transitions of the asynchronous worker object
6159         // state machine.
6160         switch (_NewState)
6161         {
6162             case _AsyncStatusInternal::_AsyncStarted:
6163                 if (_Current != _AsyncCreated)
6164                 {
6165                     return false;
6166                 }
6167                 break;
6168             case _AsyncStatusInternal::_AsyncCompleted:
6169                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
6170                 {
6171                     return false;
6172                 }
6173                 break;
6174             case _AsyncStatusInternal::_AsyncCancelPending:
6175                 if (_Current != _AsyncStarted)
6176                 {
6177                     return false;
6178                 }
6179                 break;
6180             case _AsyncStatusInternal::_AsyncCanceled:
6181                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
6182                 {
6183                     return false;
6184                 }
6185                 break;
6186             case _AsyncStatusInternal::_AsyncError:
6187                 if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
6188                 {
6189                     return false;
6190                 }
6191                 break;
6192             case _AsyncStatusInternal::_AsyncClosed:
6193                 if (!_IsTerminalState(_Current))
6194                 {
6195                     return false;
6196                 }
6197                 break;
6198             default: return false; break;
6199         }
6200 
6201         // attempt the transition to the new state
6202         // Note: if currentStatus_ == _Current, then there was no intervening write
6203         // by the async work object and the swap succeeded.
6204         _AsyncStatusInternal _RetState = static_cast<_AsyncStatusInternal>(_InterlockedCompareExchange(
6205             reinterpret_cast<volatile LONG*>(&_M_currentStatus), _NewState, static_cast<LONG>(_Current)));
6206 
6207         // ICE returns the former state, if the returned state and the
6208         // state we captured at the beginning of this method are the same,
6209         // the swap succeeded.
6210         return (_RetState == _Current);
6211     }
6212 
6213     inline bool _IsTerminalState() { return _IsTerminalState(_M_currentStatus); }
6214 
6215     inline bool _IsTerminalState(_AsyncStatusInternal status)
6216     {
6217         return (status == _AsyncError || status == _AsyncCanceled || status == _AsyncCompleted ||
6218                 status == _AsyncClosed);
6219     }
6220 
6221 private:
6222     _ContextCallback _M_completeDelegateContext;
6223     typename _Attributes::_CompletionDelegateType ^ volatile _M_completeDelegate;
6224     _AsyncStatusInternal volatile _M_currentStatus;
6225     HRESULT volatile _M_errorCode;
6226     unsigned int _M_id;
6227     long volatile _M_CompleteDelegateAssigned;
6228     long volatile _M_CallbackMade;
6229 };
6230 
6231 // ***************************************************************************
6232 // Progress Layer (optional):
6233 //
6234 
6235 template<typename _Attributes, bool _HasProgress, _AsyncResultType _ResultType = SingleResult>
6236 ref class _AsyncProgressBase abstract : _AsyncInfoBase<_Attributes, _ResultType>
6237 {
6238 };
6239 
6240 template<typename _Attributes, _AsyncResultType _ResultType>
6241 ref class _AsyncProgressBase<_Attributes, true, _ResultType> abstract : _AsyncInfoBase<_Attributes, _ResultType>
6242 {
6243     internal :
6244 
6245         _AsyncProgressBase()
6246         : _AsyncInfoBase<_Attributes, _ResultType>(), _M_progressDelegate(nullptr)
6247     {
6248     }
6249 
6250     virtual typename _Attributes::_ProgressDelegateType ^ _GetOnProgress() override
6251     {
6252         _CheckValidStateForDelegateCall();
6253         return _M_progressDelegate;
6254     }
6255 
6256     virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType ^ _ProgressHandler) override
6257     {
6258         _CheckValidStateForDelegateCall();
6259         _M_progressDelegate = _ProgressHandler;
6260         _M_progressDelegateContext = _ContextCallback::_CaptureCurrent();
6261     }
6262 
6263     void _FireProgress(const typename _Attributes::_ProgressType& _ProgressValue)
6264     {
6265         if (_M_progressDelegate != nullptr)
6266         {
6267             _M_progressDelegateContext._CallInContext(
6268                 [=] { _M_progressDelegate((_Attributes::_AsyncBaseType ^) this, _ProgressValue); });
6269         }
6270     }
6271 
6272 private:
6273     _ContextCallback _M_progressDelegateContext;
6274     typename _Attributes::_ProgressDelegateType ^ _M_progressDelegate;
6275 };
6276 
6277 template<typename _Attributes, _AsyncResultType _ResultType = SingleResult>
6278 ref class _AsyncBaseProgressLayer abstract : _AsyncProgressBase<_Attributes, _Attributes::_TakesProgress, _ResultType>
6279 {
6280 };
6281 
6282 // ***************************************************************************
6283 // Task Adaptation Layer:
6284 //
6285 
6286 //
6287 // _AsyncTaskThunkBase provides a bridge between IAsync<Action/Operation> and task.
6288 //
6289 template<typename _Attributes, typename _ReturnType>
6290 ref class _AsyncTaskThunkBase abstract : _AsyncBaseProgressLayer<_Attributes>
6291 {
6292 public:
6293     virtual _ReturnType GetResults() override
6294     {
6295         _CheckValidStateForResultsCall();
6296         return _M_task.get();
6297     }
6298 
6299     internal :
6300 
6301         typedef task<_ReturnType>
6302             _TaskType;
6303 
6304     _AsyncTaskThunkBase(const _TaskType& _Task) : _M_task(_Task) {}
6305 
6306     _AsyncTaskThunkBase() {}
6307 
6308 protected:
6309     virtual void _OnStart() override
6310     {
6311         _M_task.then([=](_TaskType _Antecedent) {
6312             try
6313             {
6314                 _Antecedent.get();
6315             }
6316             catch (task_canceled&)
6317             {
6318                 _TryTransitionToCancelled();
6319             }
6320             catch (::Platform::Exception ^ _Ex)
6321             {
6322                 _TryTransitionToError(_Ex->HResult);
6323             }
6324             catch (...)
6325             {
6326                 _TryTransitionToError(E_FAIL);
6327             }
6328             _FireCompletion();
6329         });
6330     }
6331 
6332     internal :
6333 
6334         _TaskType _M_task;
6335     cancellation_token_source _M_cts;
6336 };
6337 
6338 template<typename _Attributes>
6339 ref class _AsyncTaskThunk : _AsyncTaskThunkBase<_Attributes, typename _Attributes::_ReturnType>
6340 {
6341     internal :
6342 
6343         _AsyncTaskThunk(const _TaskType& _Task)
6344         : _AsyncTaskThunkBase(_Task)
6345     {
6346     }
6347 
6348     _AsyncTaskThunk() {}
6349 
6350 protected:
6351     virtual void _OnClose() override {}
6352 
6353     virtual void _OnCancel() override { _M_cts.cancel(); }
6354 };
6355 
6356 // ***************************************************************************
6357 // Async Creation Layer:
6358 //
6359 template<typename _Function>
6360 ref class _AsyncTaskGeneratorThunk sealed
6361     : _AsyncTaskThunk<typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes>
6362 {
6363     internal :
6364 
6365         typedef typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes _Attributes;
6366     typedef typename _AsyncTaskThunk<_Attributes> _Base;
6367     typedef typename _Attributes::_AsyncBaseType _AsyncBaseType;
6368 
6369     _AsyncTaskGeneratorThunk(const _Function& _Func, const _TaskCreationCallstack& _callstack)
6370         : _M_func(_Func), _M_creationCallstack(_callstack)
6371     {
6372         // Virtual call here is safe as the class is declared 'sealed'
6373         _Start();
6374     }
6375 
6376 protected:
6377     //
6378     // The only thing we must do different from the base class is we must spin the hot task on transition from
6379     // Created->Started. Otherwise, let the base thunk handle everything.
6380     //
6381 
6382     virtual void _OnStart() override
6383     {
6384         //
6385         // Call the appropriate task generator to actually produce a task of the expected type. This might adapt the
6386         // user lambda for progress reports, wrap the return result in a task, or allow for direct return of a task
6387         // depending on the form of the lambda.
6388         //
6389         _M_task = _Attributes::_Generate_Task(_M_func, this, _M_cts, _M_creationCallstack);
6390         _Base::_OnStart();
6391     }
6392 
6393     virtual void _OnCancel() override { _Base::_OnCancel(); }
6394 
6395 private:
6396     _TaskCreationCallstack _M_creationCallstack;
6397     _Function _M_func;
6398 };
6399 } // namespace details
6400 
6401 /// <summary>
6402 ///     Creates a Windows Runtime asynchronous construct based on a user supplied lambda or function object. The return
6403 ///     type of <c>create_async</c> is one of either <c>IAsyncAction^</c>,
6404 ///     <c>IAsyncActionWithProgress&lt;TProgress&gt;^</c>, <c>IAsyncOperation&lt;TResult&gt;^</c>, or
6405 ///     <c>IAsyncOperationWithProgress&lt;TResult, TProgress&gt;^</c> based on the signature of the lambda passed to the
6406 ///     method.
6407 /// </summary>
6408 /// <param name="_Func">
6409 ///     The lambda or function object from which to create a Windows Runtime asynchronous construct.
6410 /// </param>
6411 /// <returns>
6412 ///     An asynchronous construct represented by an IAsyncAction^, IAsyncActionWithProgress&lt;TProgress&gt;^,
6413 ///     IAsyncOperation&lt;TResult&gt;^, or an IAsyncOperationWithProgress&lt;TResult, TProgress&gt;^. The interface
6414 ///     returned depends on the signature of the lambda passed into the function.
6415 /// </returns>
6416 /// <remarks>
6417 ///     The return type of the lambda determines whether the construct is an action or an operation.
6418 ///     <para>Lambdas that return void cause the creation of actions. Lambdas that return a result of type
6419 ///     <c>TResult</c> cause the creation of operations of TResult.</para> <para>The lambda may also return a
6420 ///     <c>task&lt;TResult&gt;</c> which encapsulates the asynchronous work within itself or is the continuation of a
6421 ///     chain of tasks that represent the asynchronous work. In this case, the lambda itself is executed inline, since
6422 ///     the tasks are the ones that execute asynchronously, and the return type of the lambda is unwrapped to produce
6423 ///     the asynchronous construct returned by <c>create_async</c>. This implies that a lambda that returns a
6424 ///     task&lt;void&gt; will cause the creation of actions, and a lambda that returns a task&lt;TResult&gt; will cause
6425 ///     the creation of operations of TResult.</para> <para>The lambda may take either zero, one or two arguments. The
6426 ///     valid arguments are <c>progress_reporter&lt;TProgress&gt;</c> and <c>cancellation_token</c>, in that order if
6427 ///     both are used. A lambda without arguments causes the creation of an asynchronous construct without the
6428 ///     capability for progress reporting. A lambda that takes a progress_reporter&lt;TProgress&gt; will cause
6429 ///     <c>create_async</c> to return an asynchronous construct which reports progress of type TProgress each time the
6430 ///     <c>report</c> method of the progress_reporter object is called. A lambda that takes a cancellation_token may use
6431 ///     that token to check for cancellation, or pass it to tasks that it creates so that cancellation of the
6432 ///     asynchronous construct causes cancellation of those tasks.</para>
6433 ///     <para>If the body of the lambda or function object returns a result (and not a task&lt;TResult&gt;), the lambda
6434 ///     will be executed asynchronously within the process MTA in the context of a task the Runtime implicitly creates
6435 ///     for it. The <c>IAsyncInfo::Cancel</c> method will cause cancellation of the implicit task.</para> <para>If the
6436 ///     body of the lambda returns a task, the lambda executes inline, and by declaring the lambda to take an argument
6437 ///     of type <c>cancellation_token</c> you can trigger cancellation of any tasks you create within the lambda by
6438 ///     passing that token in when you create them. You may also use the <c>register_callback</c> method on the token to
6439 ///     cause the Runtime to invoke a callback when you call <c>IAsyncInfo::Cancel</c> on the async operation or action
6440 ///     produced..</para> <para>This function is only available to Windows Store apps.</para>
6441 /// </remarks>
6442 /// <seealso cref="task Class"/>
6443 /// <seealso cref="progress_reporter Class"/>
6444 /// <seealso cref="cancelation_token Class"/>
6445 /**/
6446 template<typename _Function>
6447     __declspec(noinline) details::_AsyncTaskGeneratorThunk<_Function> ^
6448     create_async(const _Function& _Func) {
6449         static_assert(std::is_same<decltype(details::_IsValidCreateAsync(_Func, 0, 0, 0, 0)), std::true_type>::value,
6450                       "argument to create_async must be a callable object taking zero, one or two arguments");
6451         return ref new details::_AsyncTaskGeneratorThunk<_Function>(_Func, PPLX_CAPTURE_CALLSTACK());
6452     }
6453 
6454 #endif /* defined (__cplusplus_winrt) */
6455 
6456     namespace details
6457 {
6458     // Helper struct for when_all operators to know when tasks have completed
6459     template<typename _Type>
6460     struct _RunAllParam
6461     {
6462         _RunAllParam() : _M_completeCount(0), _M_numTasks(0) {}
6463 
6464         void _Resize(size_t _Len, bool _SkipVector = false)
6465         {
6466             _M_numTasks = _Len;
6467             if (!_SkipVector)
6468             {
6469                 _M_vector._Result.resize(_Len);
6470             }
6471         }
6472 
6473         task_completion_event<_Unit_type> _M_completed;
6474         _ResultHolder<std::vector<_Type>> _M_vector;
6475         _ResultHolder<_Type> _M_mergeVal;
6476         atomic_size_t _M_completeCount;
6477         size_t _M_numTasks;
6478     };
6479 
6480     template<typename _Type>
6481     struct _RunAllParam<std::vector<_Type>>
6482     {
6483         _RunAllParam() : _M_completeCount(0), _M_numTasks(0) {}
6484 
6485         void _Resize(size_t _Len, bool _SkipVector = false)
6486         {
6487             _M_numTasks = _Len;
6488 
6489             if (!_SkipVector)
6490             {
6491                 _M_vector.resize(_Len);
6492             }
6493         }
6494 
6495         task_completion_event<_Unit_type> _M_completed;
6496         std::vector<_ResultHolder<std::vector<_Type>>> _M_vector;
6497         atomic_size_t _M_completeCount;
6498         size_t _M_numTasks;
6499     };
6500 
6501     // Helper struct specialization for void
6502     template<>
6503     struct _RunAllParam<_Unit_type>
6504     {
6505         _RunAllParam() : _M_completeCount(0), _M_numTasks(0) {}
6506 
6507         void _Resize(size_t _Len) { _M_numTasks = _Len; }
6508 
6509         task_completion_event<_Unit_type> _M_completed;
6510         atomic_size_t _M_completeCount;
6511         size_t _M_numTasks;
6512     };
6513 
6514     inline void _JoinAllTokens_Add(const cancellation_token_source& _MergedSrc,
6515                                    _CancellationTokenState* _PJoinedTokenState)
6516     {
6517         if (_PJoinedTokenState != nullptr && _PJoinedTokenState != _CancellationTokenState::_None())
6518         {
6519             cancellation_token _T = cancellation_token::_FromImpl(_PJoinedTokenState);
6520             _T.register_callback([=]() { _MergedSrc.cancel(); });
6521         }
6522     }
6523 
6524     template<typename _ElementType, typename _Function, typename _TaskType>
6525     void _WhenAllContinuationWrapper(_RunAllParam<_ElementType> * _PParam, _Function _Func, task<_TaskType> & _Task)
6526     {
6527         if (_Task._GetImpl()->_IsCompleted())
6528         {
6529             _Func();
6530             if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6531             {
6532                 // Inline execute its direct continuation, the _ReturnTask
6533                 _PParam->_M_completed.set(_Unit_type());
6534                 // It's safe to delete it since all usage of _PParam in _ReturnTask has been finished.
6535                 delete _PParam;
6536             }
6537         }
6538         else
6539         {
6540             _ASSERTE(_Task._GetImpl()->_IsCanceled());
6541             if (_Task._GetImpl()->_HasUserException())
6542             {
6543                 // _Cancel will return false if the TCE is already canceled with or without exception
6544                 _PParam->_M_completed._Cancel(_Task._GetImpl()->_GetExceptionHolder());
6545             }
6546             else
6547             {
6548                 _PParam->_M_completed._Cancel();
6549             }
6550 
6551             if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6552             {
6553                 delete _PParam;
6554             }
6555         }
6556     }
6557 
6558     template<typename _ElementType, typename _Iterator>
6559     struct _WhenAllImpl
6560     {
6561         static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions,
6562                                                         _Iterator _Begin,
6563                                                         _Iterator _End)
6564         {
6565             _CancellationTokenState* _PTokenState =
6566                 _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6567 
6568             auto _PParam = new _RunAllParam<_ElementType>();
6569             cancellation_token_source _MergedSource;
6570 
6571             // Step1: Create task completion event.
6572             task_options _Options(_TaskOptions);
6573             _Options.set_cancellation_token(_MergedSource.get_token());
6574             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6575             // The return task must be created before step 3 to enforce inline execution.
6576             auto _ReturnTask = _All_tasks_completed._Then(
6577                 [=](_Unit_type) -> std::vector<_ElementType> { return _PParam->_M_vector.Get(); }, nullptr);
6578 
6579             // Step2: Combine and check tokens, and count elements in range.
6580             if (_PTokenState)
6581             {
6582                 _JoinAllTokens_Add(_MergedSource, _PTokenState);
6583                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6584             }
6585             else
6586             {
6587                 size_t _TaskNum = 0;
6588                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6589                 {
6590                     _TaskNum++;
6591                     _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6592                 }
6593                 _PParam->_Resize(_TaskNum);
6594             }
6595 
6596             // Step3: Check states of previous tasks.
6597             if (_Begin == _End)
6598             {
6599                 _PParam->_M_completed.set(_Unit_type());
6600                 delete _PParam;
6601             }
6602             else
6603             {
6604                 size_t _Index = 0;
6605                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6606                 {
6607                     if (_PTask->is_apartment_aware())
6608                     {
6609                         _ReturnTask._SetAsync();
6610                     }
6611 
6612                     _PTask->_Then(
6613                         [_PParam, _Index](task<_ElementType> _ResultTask) {
6614                             auto _PParamCopy = _PParam;
6615                             auto _IndexCopy = _Index;
6616                             auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask]() {
6617                                 _PParamCopy->_M_vector._Result[_IndexCopy] = _ResultTask._GetImpl()->_GetResult();
6618                             };
6619 
6620                             _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6621                         },
6622                         _CancellationTokenState::_None());
6623 
6624                     _Index++;
6625                 }
6626             }
6627 
6628             return _ReturnTask;
6629         }
6630     };
6631 
6632     template<typename _ElementType, typename _Iterator>
6633     struct _WhenAllImpl<std::vector<_ElementType>, _Iterator>
6634     {
6635         static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions,
6636                                                         _Iterator _Begin,
6637                                                         _Iterator _End)
6638         {
6639             _CancellationTokenState* _PTokenState =
6640                 _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6641 
6642             auto _PParam = new _RunAllParam<std::vector<_ElementType>>();
6643             cancellation_token_source _MergedSource;
6644 
6645             // Step1: Create task completion event.
6646             task_options _Options(_TaskOptions);
6647             _Options.set_cancellation_token(_MergedSource.get_token());
6648             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6649             // The return task must be created before step 3 to enforce inline execution.
6650             auto _ReturnTask = _All_tasks_completed._Then(
6651                 [=](_Unit_type) -> std::vector<_ElementType> {
6652                     _ASSERTE(_PParam->_M_completeCount == _PParam->_M_numTasks);
6653                     std::vector<_ElementType> _Result;
6654                     for (size_t _I = 0; _I < _PParam->_M_numTasks; _I++)
6655                     {
6656                         const std::vector<_ElementType>& _Vec = _PParam->_M_vector[_I].Get();
6657                         _Result.insert(_Result.end(), _Vec.begin(), _Vec.end());
6658                     }
6659                     return _Result;
6660                 },
6661                 nullptr);
6662 
6663             // Step2: Combine and check tokens, and count elements in range.
6664             if (_PTokenState)
6665             {
6666                 _JoinAllTokens_Add(_MergedSource, _PTokenState);
6667                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6668             }
6669             else
6670             {
6671                 size_t _TaskNum = 0;
6672                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6673                 {
6674                     _TaskNum++;
6675                     _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6676                 }
6677                 _PParam->_Resize(_TaskNum);
6678             }
6679 
6680             // Step3: Check states of previous tasks.
6681             if (_Begin == _End)
6682             {
6683                 _PParam->_M_completed.set(_Unit_type());
6684                 delete _PParam;
6685             }
6686             else
6687             {
6688                 size_t _Index = 0;
6689                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6690                 {
6691                     if (_PTask->is_apartment_aware())
6692                     {
6693                         _ReturnTask._SetAsync();
6694                     }
6695 
6696                     _PTask->_Then(
6697                         [_PParam, _Index](task<std::vector<_ElementType>> _ResultTask) {
6698                             auto _PParamCopy = _PParam;
6699                             auto _IndexCopy = _Index;
6700                             auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask]() {
6701                                 _PParamCopy->_M_vector[_IndexCopy].Set(_ResultTask._GetImpl()->_GetResult());
6702                             };
6703 
6704                             _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6705                         },
6706                         _CancellationTokenState::_None());
6707 
6708                     _Index++;
6709                 }
6710             }
6711 
6712             return _ReturnTask;
6713         }
6714     };
6715 
6716     template<typename _Iterator>
6717     struct _WhenAllImpl<void, _Iterator>
6718     {
6719         static task<void> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6720         {
6721             _CancellationTokenState* _PTokenState =
6722                 _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6723 
6724             auto _PParam = new _RunAllParam<_Unit_type>();
6725             cancellation_token_source _MergedSource;
6726 
6727             // Step1: Create task completion event.
6728             task_options _Options(_TaskOptions);
6729             _Options.set_cancellation_token(_MergedSource.get_token());
6730             task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6731             // The return task must be created before step 3 to enforce inline execution.
6732             auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) {}, nullptr);
6733 
6734             // Step2: Combine and check tokens, and count elements in range.
6735             if (_PTokenState)
6736             {
6737                 _JoinAllTokens_Add(_MergedSource, _PTokenState);
6738                 _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6739             }
6740             else
6741             {
6742                 size_t _TaskNum = 0;
6743                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6744                 {
6745                     _TaskNum++;
6746                     _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6747                 }
6748                 _PParam->_Resize(_TaskNum);
6749             }
6750 
6751             // Step3: Check states of previous tasks.
6752             if (_Begin == _End)
6753             {
6754                 _PParam->_M_completed.set(_Unit_type());
6755                 delete _PParam;
6756             }
6757             else
6758             {
6759                 for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6760                 {
6761                     if (_PTask->is_apartment_aware())
6762                     {
6763                         _ReturnTask._SetAsync();
6764                     }
6765 
6766                     _PTask->_Then(
6767                         [_PParam](task<void> _ResultTask) {
6768                             auto _Func = []() {};
6769                             _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6770                         },
6771                         _CancellationTokenState::_None());
6772                 }
6773             }
6774 
6775             return _ReturnTask;
6776         }
6777     };
6778 
6779     template<typename _ReturnType>
6780     task<std::vector<_ReturnType>> _WhenAllVectorAndValue(
6781         const task<std::vector<_ReturnType>>& _VectorTask, const task<_ReturnType>& _ValueTask, bool _OutputVectorFirst)
6782     {
6783         auto _PParam = new _RunAllParam<_ReturnType>();
6784         cancellation_token_source _MergedSource;
6785 
6786         // Step1: Create task completion event.
6787         task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
6788         // The return task must be created before step 3 to enforce inline execution.
6789         auto _ReturnTask = _All_tasks_completed._Then(
6790             [=](_Unit_type) -> std::vector<_ReturnType> {
6791                 _ASSERTE(_PParam->_M_completeCount == 2);
6792                 auto _Result = _PParam->_M_vector.Get(); // copy by value
6793                 auto _mergeVal = _PParam->_M_mergeVal.Get();
6794 
6795                 if (_OutputVectorFirst == true)
6796                 {
6797                     _Result.push_back(_mergeVal);
6798                 }
6799                 else
6800                 {
6801                     _Result.insert(_Result.begin(), _mergeVal);
6802                 }
6803                 return _Result;
6804             },
6805             nullptr);
6806 
6807         // Step2: Combine and check tokens.
6808         _JoinAllTokens_Add(_MergedSource, _VectorTask._GetImpl()->_M_pTokenState);
6809         _JoinAllTokens_Add(_MergedSource, _ValueTask._GetImpl()->_M_pTokenState);
6810 
6811         // Step3: Check states of previous tasks.
6812         _PParam->_Resize(2, true);
6813 
6814         if (_VectorTask.is_apartment_aware() || _ValueTask.is_apartment_aware())
6815         {
6816             _ReturnTask._SetAsync();
6817         }
6818         _VectorTask._Then(
6819             [_PParam](task<std::vector<_ReturnType>> _ResultTask) {
6820                 auto _PParamCopy = _PParam;
6821                 auto _Func = [_PParamCopy, &_ResultTask]() {
6822                     auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6823                     _PParamCopy->_M_vector.Set(_ResultLocal);
6824                 };
6825 
6826                 _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6827             },
6828             _CancellationTokenState::_None());
6829         _ValueTask._Then(
6830             [_PParam](task<_ReturnType> _ResultTask) {
6831                 auto _PParamCopy = _PParam;
6832                 auto _Func = [_PParamCopy, &_ResultTask]() {
6833                     auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6834                     _PParamCopy->_M_mergeVal.Set(_ResultLocal);
6835                 };
6836 
6837                 _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6838             },
6839             _CancellationTokenState::_None());
6840 
6841         return _ReturnTask;
6842     }
6843 } // namespace details
6844 
6845 /// <summary>
6846 ///     Creates a task that will complete successfully when all of the tasks supplied as arguments complete
6847 ///     successfully.
6848 /// </summary>
6849 /// <typeparam name="_Iterator">
6850 ///     The type of the input iterator.
6851 /// </typeparam>
6852 /// <param name="_Begin">
6853 ///     The position of the first element in the range of elements to be combined into the resulting task.
6854 /// </param>
6855 /// <param name="_End">
6856 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
6857 /// </param>
6858 /// <returns>
6859 ///     A task that completes successfully when all of the input tasks have completed successfully. If the input tasks
6860 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the
6861 ///     input tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>.
6862 /// </returns>
6863 /// <remarks>
6864 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled
6865 ///     state, and the exception, if one is encountered, will be thrown if you call <c>get()</c> or <c>wait()</c> on
6866 ///     that task.
6867 /// </remarks>
6868 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6869 /**/
6870 template<typename _Iterator>
6871 auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
6872     -> decltype(details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type,
6873                                       _Iterator>::_Perform(_TaskOptions, _Begin, _End))
6874 {
6875     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6876     return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
6877 }
6878 
6879 /// <summary>
6880 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete
6881 ///     successfully.
6882 /// </summary>
6883 /// <typeparam name="_ReturnType">
6884 ///     The type of the returned task.
6885 /// </typeparam>
6886 /// <param name="_Lhs">
6887 ///     The first task to combine into the resulting task.
6888 /// </param>
6889 /// <param name="_Rhs">
6890 ///     The second task to combine into the resulting task.
6891 /// </param>
6892 /// <returns>
6893 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks
6894 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the
6895 ///     input tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for
6896 ///     a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp;
6897 ///     operator produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type
6898 ///     <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
6899 /// </returns>
6900 /// <remarks>
6901 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled
6902 ///     state, and the exception, if one is encountered, will be thrown if you call <c>get()</c> or <c>wait()</c> on
6903 ///     that task.
6904 /// </remarks>
6905 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6906 /**/
6907 template<typename _ReturnType>
6908 auto operator&&(const task<_ReturnType>& _Lhs, const task<_ReturnType>& _Rhs) -> decltype(when_all(&_Lhs, &_Lhs))
6909 {
6910     task<_ReturnType> _PTasks[2] = {_Lhs, _Rhs};
6911     return when_all(_PTasks, _PTasks + 2);
6912 }
6913 
6914 /// <summary>
6915 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete
6916 ///     successfully.
6917 /// </summary>
6918 /// <typeparam name="_ReturnType">
6919 ///     The type of the returned task.
6920 /// </typeparam>
6921 /// <param name="_Lhs">
6922 ///     The first task to combine into the resulting task.
6923 /// </param>
6924 /// <param name="_Rhs">
6925 ///     The second task to combine into the resulting task.
6926 /// </param>
6927 /// <returns>
6928 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks
6929 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the
6930 ///     input tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for
6931 ///     a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp;
6932 ///     operator produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type
6933 ///     <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
6934 /// </returns>
6935 /// <remarks>
6936 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled
6937 ///     state, and the exception, if one is encountered, will be thrown if you call <c>get()</c> or <c>wait()</c> on
6938 ///     that task.
6939 /// </remarks>
6940 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6941 /**/
6942 template<typename _ReturnType>
6943 auto operator&&(const task<std::vector<_ReturnType>>& _Lhs, const task<_ReturnType>& _Rhs)
6944     -> decltype(details::_WhenAllVectorAndValue(_Lhs, _Rhs, true))
6945 {
6946     return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true);
6947 }
6948 
6949 /// <summary>
6950 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete
6951 ///     successfully.
6952 /// </summary>
6953 /// <typeparam name="_ReturnType">
6954 ///     The type of the returned task.
6955 /// </typeparam>
6956 /// <param name="_Lhs">
6957 ///     The first task to combine into the resulting task.
6958 /// </param>
6959 /// <param name="_Rhs">
6960 ///     The second task to combine into the resulting task.
6961 /// </param>
6962 /// <returns>
6963 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks
6964 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the
6965 ///     input tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for
6966 ///     a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp;
6967 ///     operator produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type
6968 ///     <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
6969 /// </returns>
6970 /// <remarks>
6971 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled
6972 ///     state, and the exception, if one is encountered, will be thrown if you call <c>get()</c> or <c>wait()</c> on
6973 ///     that task.
6974 /// </remarks>
6975 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
6976 /**/
6977 template<typename _ReturnType>
6978 auto operator&&(const task<_ReturnType>& _Lhs, const task<std::vector<_ReturnType>>& _Rhs)
6979     -> decltype(details::_WhenAllVectorAndValue(_Rhs, _Lhs, false))
6980 {
6981     return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false);
6982 }
6983 
6984 /// <summary>
6985 ///     Creates a task that will complete successfully when both of the tasks supplied as arguments complete
6986 ///     successfully.
6987 /// </summary>
6988 /// <typeparam name="_ReturnType">
6989 ///     The type of the returned task.
6990 /// </typeparam>
6991 /// <param name="_Lhs">
6992 ///     The first task to combine into the resulting task.
6993 /// </param>
6994 /// <param name="_Rhs">
6995 ///     The second task to combine into the resulting task.
6996 /// </param>
6997 /// <returns>
6998 ///     A task that completes successfully when both of the input tasks have completed successfully. If the input tasks
6999 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;&gt;</c>. If the
7000 ///     input tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for
7001 ///     a construct of the sort taskA &amp;&amp; taskB &amp;&amp; taskC, which are combined in pairs, the &amp;&amp;
7002 ///     operator produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if either one or both of the tasks are of type
7003 ///     <c>task&lt;std::vector&lt;T&gt;&gt;</c>.</para>
7004 /// </returns>
7005 /// <remarks>
7006 ///     If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled
7007 ///     state, and the exception, if one is encountered, will be thrown if you call <c>get()</c> or <c>wait()</c> on
7008 ///     that task.
7009 /// </remarks>
7010 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7011 /**/
7012 template<typename _ReturnType>
7013 auto operator&&(const task<std::vector<_ReturnType>>& _Lhs, const task<std::vector<_ReturnType>>& _Rhs)
7014     -> decltype(when_all(&_Lhs, &_Lhs))
7015 {
7016     task<std::vector<_ReturnType>> _PTasks[2] = {_Lhs, _Rhs};
7017     return when_all(_PTasks, _PTasks + 2);
7018 }
7019 
7020 namespace details
7021 {
7022 // Helper struct for when_any operators to know when tasks have completed
7023 template<typename _CompletionType>
7024 struct _RunAnyParam
7025 {
7026     _RunAnyParam() : _M_exceptionRelatedToken(nullptr), _M_completeCount(0), _M_numTasks(0), _M_fHasExplicitToken(false)
7027     {
7028     }
7029     ~_RunAnyParam()
7030     {
7031         if (_CancellationTokenState::_IsValid(_M_exceptionRelatedToken)) _M_exceptionRelatedToken->_Release();
7032     }
7033     task_completion_event<_CompletionType> _M_Completed;
7034     cancellation_token_source _M_cancellationSource;
7035     _CancellationTokenState* _M_exceptionRelatedToken;
7036     atomic_size_t _M_completeCount;
7037     size_t _M_numTasks;
7038     bool _M_fHasExplicitToken;
7039 };
7040 
7041 template<typename _CompletionType, typename _Function, typename _TaskType>
7042 void _WhenAnyContinuationWrapper(_RunAnyParam<_CompletionType>* _PParam, const _Function& _Func, task<_TaskType>& _Task)
7043 {
7044     bool _IsTokenCancled = !_PParam->_M_fHasExplicitToken &&
7045                            _Task._GetImpl()->_M_pTokenState != _CancellationTokenState::_None() &&
7046                            _Task._GetImpl()->_M_pTokenState->_IsCanceled();
7047     if (_Task._GetImpl()->_IsCompleted() && !_IsTokenCancled)
7048     {
7049         _Func();
7050         if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
7051         {
7052             delete _PParam;
7053         }
7054     }
7055     else
7056     {
7057         _ASSERTE(_Task._GetImpl()->_IsCanceled() || _IsTokenCancled);
7058         if (_Task._GetImpl()->_HasUserException() && !_IsTokenCancled)
7059         {
7060             if (_PParam->_M_Completed._StoreException(_Task._GetImpl()->_GetExceptionHolder()))
7061             {
7062                 // This can only enter once.
7063                 _PParam->_M_exceptionRelatedToken = _Task._GetImpl()->_M_pTokenState;
7064                 _ASSERTE(_PParam->_M_exceptionRelatedToken);
7065                 // Deref token will be done in the _PParam destructor.
7066                 if (_PParam->_M_exceptionRelatedToken != _CancellationTokenState::_None())
7067                 {
7068                     _PParam->_M_exceptionRelatedToken->_Reference();
7069                 }
7070             }
7071         }
7072 
7073         if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
7074         {
7075             // If no one has be completed so far, we need to make some final cancellation decision.
7076             if (!_PParam->_M_Completed._IsTriggered())
7077             {
7078                 // If we already explicit token, we can skip the token join part.
7079                 if (!_PParam->_M_fHasExplicitToken)
7080                 {
7081                     if (_PParam->_M_exceptionRelatedToken)
7082                     {
7083                         _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PParam->_M_exceptionRelatedToken);
7084                     }
7085                     else
7086                     {
7087                         // If haven't captured any exception token yet, there was no exception for all those tasks,
7088                         // so just pick a random token (current one) for normal cancellation.
7089                         _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Task._GetImpl()->_M_pTokenState);
7090                     }
7091                 }
7092                 // Do exception cancellation or normal cancellation based on whether it has stored exception.
7093                 _PParam->_M_Completed._Cancel();
7094             }
7095             delete _PParam;
7096         }
7097     }
7098 }
7099 
7100 template<typename _ElementType, typename _Iterator>
7101 struct _WhenAnyImpl
7102 {
7103     static task<std::pair<_ElementType, size_t>> _Perform(const task_options& _TaskOptions,
7104                                                           _Iterator _Begin,
7105                                                           _Iterator _End)
7106     {
7107         if (_Begin == _End)
7108         {
7109             throw invalid_operation("when_any(begin, end) cannot be called on an empty container.");
7110         }
7111         _CancellationTokenState* _PTokenState =
7112             _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
7113         auto _PParam = new _RunAnyParam<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState*>>();
7114 
7115         if (_PTokenState)
7116         {
7117             _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
7118             _PParam->_M_fHasExplicitToken = true;
7119         }
7120 
7121         task_options _Options(_TaskOptions);
7122         _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
7123         task<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState*>> _Any_tasks_completed(
7124             _PParam->_M_Completed, _Options);
7125 
7126         // Keep a copy ref to the token source
7127         auto _CancellationSource = _PParam->_M_cancellationSource;
7128 
7129         _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
7130         size_t _Index = 0;
7131         for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
7132         {
7133             if (_PTask->is_apartment_aware())
7134             {
7135                 _Any_tasks_completed._SetAsync();
7136             }
7137 
7138             _PTask->_Then(
7139                 [_PParam, _Index](task<_ElementType> _ResultTask) {
7140                     auto _PParamCopy = _PParam; // Dev10
7141                     auto _IndexCopy = _Index;   // Dev10
7142                     auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
7143                         _PParamCopy->_M_Completed.set(
7144                             std::make_pair(std::make_pair(_ResultTask._GetImpl()->_GetResult(), _IndexCopy),
7145                                            _ResultTask._GetImpl()->_M_pTokenState));
7146                     };
7147 
7148                     _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7149                 },
7150                 _CancellationTokenState::_None());
7151 
7152             _Index++;
7153         }
7154 
7155         // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
7156         return _Any_tasks_completed._Then(
7157             [=](std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState*> _Result)
7158                 -> std::pair<_ElementType, size_t> {
7159                 _ASSERTE(_Result.second);
7160                 if (!_PTokenState)
7161                 {
7162                     _JoinAllTokens_Add(_CancellationSource, _Result.second);
7163                 }
7164                 return _Result.first;
7165             },
7166             nullptr);
7167     }
7168 };
7169 
7170 template<typename _Iterator>
7171 struct _WhenAnyImpl<void, _Iterator>
7172 {
7173     static task<size_t> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
7174     {
7175         if (_Begin == _End)
7176         {
7177             throw invalid_operation("when_any(begin, end) cannot be called on an empty container.");
7178         }
7179 
7180         _CancellationTokenState* _PTokenState =
7181             _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
7182         auto _PParam = new _RunAnyParam<std::pair<size_t, _CancellationTokenState*>>();
7183 
7184         if (_PTokenState)
7185         {
7186             _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
7187             _PParam->_M_fHasExplicitToken = true;
7188         }
7189 
7190         task_options _Options(_TaskOptions);
7191         _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
7192         task<std::pair<size_t, _CancellationTokenState*>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
7193 
7194         // Keep a copy ref to the token source
7195         auto _CancellationSource = _PParam->_M_cancellationSource;
7196 
7197         _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
7198         size_t _Index = 0;
7199         for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
7200         {
7201             if (_PTask->is_apartment_aware())
7202             {
7203                 _Any_tasks_completed._SetAsync();
7204             }
7205 
7206             _PTask->_Then(
7207                 [_PParam, _Index](task<void> _ResultTask) {
7208                     auto _PParamCopy = _PParam; // Dev10
7209                     auto _IndexCopy = _Index;   // Dev10
7210                     auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
7211                         _PParamCopy->_M_Completed.set(
7212                             std::make_pair(_IndexCopy, _ResultTask._GetImpl()->_M_pTokenState));
7213                     };
7214                     _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7215                 },
7216                 _CancellationTokenState::_None());
7217 
7218             _Index++;
7219         }
7220 
7221         // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
7222         return _Any_tasks_completed._Then(
7223             [=](std::pair<size_t, _CancellationTokenState*> _Result) -> size_t {
7224                 _ASSERTE(_Result.second);
7225                 if (!_PTokenState)
7226                 {
7227                     _JoinAllTokens_Add(_CancellationSource, _Result.second);
7228                 }
7229                 return _Result.first;
7230             },
7231             nullptr);
7232     }
7233 };
7234 } // namespace details
7235 
7236 /// <summary>
7237 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes
7238 ///     successfully.
7239 /// </summary>
7240 /// <typeparam name="_Iterator">
7241 ///     The type of the input iterator.
7242 /// </typeparam>
7243 /// <param name="_Begin">
7244 ///     The position of the first element in the range of elements to be combined into the resulting task.
7245 /// </param>
7246 /// <param name="_End">
7247 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
7248 /// </param>
7249 /// <returns>
7250 ///     A task that completes successfully when any one of the input tasks has completed successfully. If the input
7251 ///     tasks are of type <c>T</c>, the output of this function will be a <c>task&lt;std::pair&lt;T,
7252 ///     size_t&gt;&gt;></c>, where the first element of the pair is the result of the completing task, and the second
7253 ///     element is the index of the task that finished. If the input tasks are of type <c>void</c> the output is a
7254 ///     <c>task&lt;size_t&gt;</c>, where the result is the index of the completing task.
7255 /// </returns>
7256 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7257 /**/
7258 template<typename _Iterator>
7259 auto when_any(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
7260     -> decltype(details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type,
7261                                       _Iterator>::_Perform(_TaskOptions, _Begin, _End))
7262 {
7263     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
7264     return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
7265 }
7266 
7267 /// <summary>
7268 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes
7269 ///     successfully.
7270 /// </summary>
7271 /// <typeparam name="_Iterator">
7272 ///     The type of the input iterator.
7273 /// </typeparam>
7274 /// <param name="_Begin">
7275 ///     The position of the first element in the range of elements to be combined into the resulting task.
7276 /// </param>
7277 /// <param name="_End">
7278 ///     The position of the first element beyond the range of elements to be combined into the resulting task.
7279 /// </param>
7280 /// <param name="_CancellationToken">
7281 ///     The cancellation token which controls cancellation of the returned task. If you do not provide a cancellation
7282 ///     token, the resulting task will receive the cancellation token of the task that causes it to complete.
7283 /// </param>
7284 /// <returns>
7285 ///     A task that completes successfully when any one of the input tasks has completed successfully. If the input
7286 ///     tasks are of type <c>T</c>, the output of this function will be a <c>task&lt;std::pair&lt;T,
7287 ///     size_t&gt;&gt;></c>, where the first element of the pair is the result of the completing task, and the second
7288 ///     element is the index of the task that finished. If the input tasks are of type <c>void</c> the output is a
7289 ///     <c>task&lt;size_t&gt;</c>, where the result is the index of the completing task.
7290 /// </returns>
7291 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7292 /**/
7293 template<typename _Iterator>
7294 auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _CancellationToken)
7295     -> decltype(details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type,
7296                                       _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End))
7297 {
7298     typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
7299     return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End);
7300 }
7301 
7302 /// <summary>
7303 ///     Creates a task that will complete successfully when either of the tasks supplied as arguments completes
7304 ///     successfully.
7305 /// </summary>
7306 /// <typeparam name="_ReturnType">
7307 ///     The type of the returned task.
7308 /// </typeparam>
7309 /// <param name="_Lhs">
7310 ///     The first task to combine into the resulting task.
7311 /// </param>
7312 /// <param name="_Rhs">
7313 ///     The second task to combine into the resulting task.
7314 /// </param>
7315 /// <returns>
7316 ///     A task that completes successfully when either of the input tasks has completed successfully. If the input tasks
7317 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input
7318 ///     tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for a
7319 ///     construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking
7320 ///     precedence over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of
7321 ///     type <c>task&lt;std::vector&lt;T&gt;&gt;</c> and the other one is of type <c>task&lt;T&gt;.</c></para>
7322 /// </returns>
7323 /// <remarks>
7324 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state,
7325 ///     and one of the exceptions, if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on
7326 ///     that task.
7327 /// </remarks>
7328 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7329 /**/
7330 template<typename _ReturnType>
7331 task<_ReturnType> operator||(const task<_ReturnType>& _Lhs, const task<_ReturnType>& _Rhs)
7332 {
7333     auto _PParam = new details::_RunAnyParam<std::pair<_ReturnType, size_t>>();
7334 
7335     task<std::pair<_ReturnType, size_t>> _Any_tasks_completed(_PParam->_M_Completed,
7336                                                               _PParam->_M_cancellationSource.get_token());
7337     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7338     // So that _PParam can be used before it getting deleted.
7339     auto _ReturnTask = _Any_tasks_completed._Then(
7340         [=](std::pair<_ReturnType, size_t> _Ret) -> _ReturnType {
7341             _ASSERTE(_Ret.second);
7342             _JoinAllTokens_Add(_PParam->_M_cancellationSource,
7343                                reinterpret_cast<details::_CancellationTokenState*>(_Ret.second));
7344             return _Ret.first;
7345         },
7346         nullptr);
7347 
7348     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7349     {
7350         _ReturnTask._SetAsync();
7351     }
7352 
7353     _PParam->_M_numTasks = 2;
7354     auto _Continuation = [_PParam](task<_ReturnType> _ResultTask) {
7355         //  Dev10 compiler bug
7356         auto _PParamCopy = _PParam;
7357         auto _Func = [&_ResultTask, _PParamCopy]() {
7358             _PParamCopy->_M_Completed.set(
7359                 std::make_pair(_ResultTask._GetImpl()->_GetResult(),
7360                                reinterpret_cast<size_t>(_ResultTask._GetImpl()->_M_pTokenState)));
7361         };
7362         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7363     };
7364 
7365     _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
7366     _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
7367 
7368     return _ReturnTask;
7369 }
7370 
7371 /// <summary>
7372 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes
7373 ///     successfully.
7374 /// </summary>
7375 /// <typeparam name="_ReturnType">
7376 ///     The type of the returned task.
7377 /// </typeparam>
7378 /// <param name="_Lhs">
7379 ///     The first task to combine into the resulting task.
7380 /// </param>
7381 /// <param name="_Rhs">
7382 ///     The second task to combine into the resulting task.
7383 /// </param>
7384 /// <returns>
7385 ///     A task that completes successfully when either of the input tasks has completed successfully. If the input tasks
7386 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input
7387 ///     tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for a
7388 ///     construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking
7389 ///     precedence over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of
7390 ///     type <c>task&lt;std::vector&lt;T&gt;&gt;</c> and the other one is of type <c>task&lt;T&gt;.</c></para>
7391 /// </returns>
7392 /// <remarks>
7393 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state,
7394 ///     and one of the exceptions, if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on
7395 ///     that task.
7396 /// </remarks>
7397 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7398 /**/
7399 template<typename _ReturnType>
7400 task<std::vector<_ReturnType>> operator||(const task<std::vector<_ReturnType>>& _Lhs, const task<_ReturnType>& _Rhs)
7401 {
7402     auto _PParam = new details::_RunAnyParam<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState*>>();
7403 
7404     task<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState*>> _Any_tasks_completed(
7405         _PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7406 
7407     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7408     // So that _PParam can be used before it getting deleted.
7409     auto _ReturnTask = _Any_tasks_completed._Then(
7410         [=](std::pair<std::vector<_ReturnType>, details::_CancellationTokenState*> _Ret) -> std::vector<_ReturnType> {
7411             _ASSERTE(_Ret.second);
7412             _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
7413             return _Ret.first;
7414         },
7415         nullptr);
7416 
7417     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7418     {
7419         _ReturnTask._SetAsync();
7420     }
7421 
7422     _PParam->_M_numTasks = 2;
7423     _Lhs._Then(
7424         [_PParam](task<std::vector<_ReturnType>> _ResultTask) {
7425             //  Dev10 compiler bug
7426             auto _PParamCopy = _PParam;
7427             auto _Func = [&_ResultTask, _PParamCopy]() {
7428                 auto _Result = _ResultTask._GetImpl()->_GetResult();
7429                 _PParamCopy->_M_Completed.set(std::make_pair(_Result, _ResultTask._GetImpl()->_M_pTokenState));
7430             };
7431             _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7432         },
7433         details::_CancellationTokenState::_None());
7434 
7435     _Rhs._Then(
7436         [_PParam](task<_ReturnType> _ResultTask) {
7437             auto _PParamCopy = _PParam;
7438             auto _Func = [&_ResultTask, _PParamCopy]() {
7439                 auto _Result = _ResultTask._GetImpl()->_GetResult();
7440 
7441                 std::vector<_ReturnType> _Vec;
7442                 _Vec.push_back(_Result);
7443                 _PParamCopy->_M_Completed.set(std::make_pair(_Vec, _ResultTask._GetImpl()->_M_pTokenState));
7444             };
7445             _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7446         },
7447         details::_CancellationTokenState::_None());
7448 
7449     return _ReturnTask;
7450 }
7451 
7452 /// <summary>
7453 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes
7454 ///     successfully.
7455 /// </summary>
7456 /// <typeparam name="_ReturnType">
7457 ///     The type of the returned task.
7458 /// </typeparam>
7459 /// <param name="_Lhs">
7460 ///     The first task to combine into the resulting task.
7461 /// </param>
7462 /// <param name="_Rhs">
7463 ///     The second task to combine into the resulting task.
7464 /// </param>
7465 /// <returns>
7466 ///     A task that completes successfully when either of the input tasks has completed successfully. If the input tasks
7467 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input
7468 ///     tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for a
7469 ///     construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking
7470 ///     precedence over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of
7471 ///     type <c>task&lt;std::vector&lt;T&gt;&gt;</c> and the other one is of type <c>task&lt;T&gt;.</c></para>
7472 /// </returns>
7473 /// <remarks>
7474 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state,
7475 ///     and one of the exceptions, if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on
7476 ///     that task.
7477 /// </remarks>
7478 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7479 /**/
7480 template<typename _ReturnType>
7481 auto operator||(const task<_ReturnType>& _Lhs, const task<std::vector<_ReturnType>>& _Rhs) -> decltype(_Rhs || _Lhs)
7482 {
7483     return _Rhs || _Lhs;
7484 }
7485 
7486 /// <summary>
7487 ///     Creates a task that will complete successfully when any of the tasks supplied as arguments completes
7488 ///     successfully.
7489 /// </summary>
7490 /// <typeparam name="_ReturnType">
7491 ///     The type of the returned task.
7492 /// </typeparam>
7493 /// <param name="_Lhs">
7494 ///     The first task to combine into the resulting task.
7495 /// </param>
7496 /// <param name="_Rhs">
7497 ///     The second task to combine into the resulting task.
7498 /// </param>
7499 /// <returns>
7500 ///     A task that completes successfully when either of the input tasks has completed successfully. If the input tasks
7501 ///     are of type <c>T</c>, the output of this function will be a <c>task&lt;std::vector&lt;T&gt;</c>. If the input
7502 ///     tasks are of type <c>void</c> the output task will also be a <c>task&lt;void&gt;</c>. <para> To allow for a
7503 ///     construct of the sort taskA || taskB &amp;&amp; taskC, which are combined in pairs, with &amp;&amp; taking
7504 ///     precedence over ||, the operator|| produces a <c>task&lt;std::vector&lt;T&gt;&gt;</c> if one of the tasks is of
7505 ///     type <c>task&lt;std::vector&lt;T&gt;&gt;</c> and the other one is of type <c>task&lt;T&gt;.</c></para>
7506 /// </returns>
7507 /// <remarks>
7508 ///     If both of the tasks are canceled or throw exceptions, the returned task will complete in the canceled state,
7509 ///     and one of the exceptions, if any are encountered, will be thrown when you call <c>get()</c> or <c>wait()</c> on
7510 ///     that task.
7511 /// </remarks>
7512 /// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
7513 /**/
7514 template<typename _Ty = task<void>, typename _Pair = std::pair<details::_Unit_type, details::_CancellationTokenState*>>
7515 _Ty operator||(const task<void>& _Lhs_arg, const task<void>& _Rhs_arg)
7516 {
7517     const _Ty& _Lhs = _Lhs_arg;
7518     const _Ty& _Rhs = _Rhs_arg;
7519     auto _PParam = new details::_RunAnyParam<_Pair>();
7520 
7521     task<std::pair<details::_Unit_type, details::_CancellationTokenState*>> _Any_task_completed(
7522         _PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7523     // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7524     // So that _PParam can be used before it getting deleted.
7525     auto _ReturnTask = _Any_task_completed._Then(
7526         [=](_Pair _Ret) {
7527             _ASSERTE(_Ret.second);
7528             details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
7529         },
7530         nullptr);
7531 
7532     if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7533     {
7534         _ReturnTask._SetAsync();
7535     }
7536 
7537     _PParam->_M_numTasks = 2;
7538     auto _Continuation = [_PParam](_Ty _ResultTask) mutable {
7539         //  Dev10 compiler needs this.
7540         auto _PParam1 = _PParam;
7541         auto _Func = [&_ResultTask, _PParam1]() {
7542             _PParam1->_M_Completed.set(std::make_pair(details::_Unit_type(), _ResultTask._GetImpl()->_M_pTokenState));
7543         };
7544         _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7545     };
7546 
7547     _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
7548     _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
7549 
7550     return _ReturnTask;
7551 }
7552 
7553 template<typename _Ty>
7554 task<_Ty> task_from_result(_Ty _Param, const task_options& _TaskOptions = task_options())
7555 {
7556     task_completion_event<_Ty> _Tce;
7557     _Tce.set(_Param);
7558     return create_task(_Tce, _TaskOptions);
7559 }
7560 
7561 template<class _Ty = void>
7562 inline task<_Ty> task_from_result(const task_options& _TaskOptions = task_options())
7563 {
7564     task_completion_event<_Ty> _Tce;
7565     _Tce.set();
7566     return create_task(_Tce, _TaskOptions);
7567 }
7568 
7569 template<typename _TaskType, typename _ExType>
7570 task<_TaskType> task_from_exception(_ExType _Exception, const task_options& _TaskOptions = task_options())
7571 {
7572     task_completion_event<_TaskType> _Tce;
7573     _Tce.set_exception(_Exception);
7574     return create_task(_Tce, _TaskOptions);
7575 }
7576 
7577 } // namespace pplx
7578 
7579 #pragma pop_macro("new")
7580 
7581 #if defined(_MSC_VER)
7582 #pragma warning(pop)
7583 #endif
7584 #pragma pack(pop)
7585 
7586 #endif // (defined(_MSC_VER) && (_MSC_VER >= 1800))
7587 
7588 #ifndef _CONCRT_H
7589 #ifndef _LWRCASE_CNCRRNCY
7590 #define _LWRCASE_CNCRRNCY
7591 // Note to reader: we're using lower-case namespace names everywhere, but the 'Concurrency' namespace
7592 // is capitalized for historical reasons. The alias let's us pretend that style issue doesn't exist.
7593 namespace Concurrency
7594 {
7595 }
7596 namespace concurrency = Concurrency;
7597 #endif
7598 #endif
7599 
7600 #endif // PPLXTASKS_H
7601