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