HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Nougat 7.1
|
7.1.1_r28
下载
查看原文件
收藏
根目录
external
opencv3
modules
highgui
src
ppltasks_winrt.h
/*** * ==++== * * Copyright (c) Microsoft Corporation. All rights reserved. * * Modified for native C++ WRL support by Gregory Morse * * ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * ppltasks_winrt.h * * Parallel Patterns Library - PPL Tasks * * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ #pragma once #ifndef _PPLTASKS_WINRT_H #define _PPLTASKS_WINRT_H #include
#include
#if _MSC_VER >= 1800 #include
// Cannot build using a compiler that is older than dev10 SP1 #ifdef _MSC_VER #if _MSC_FULL_VER < 160040219 /*IFSTRIP=IGN*/ #error ERROR: Visual Studio 2010 SP1 or later is required to build ppltasks #endif /*IFSTRIP=IGN*/ #endif #else #include
#endif #include
#include
#include
#include
#if _MSC_VER >= 1800 #include
#endif #ifndef __cplusplus_winrt #include
#include
#if _MSC_VER >= 1800 #include "agile_wrl.h" #endif #include
#include
#ifndef _UITHREADCTXT_SUPPORT #ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/ // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user #include
#if WINAPI_FAMILY == WINAPI_FAMILY_APP /*IFSTRIP=IGN*/ // UI thread context support is not required for desktop and Windows Store apps #define _UITHREADCTXT_SUPPORT 0 #elif WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP /*IFSTRIP=IGN*/ // UI thread context support is not required for desktop and Windows Store apps #define _UITHREADCTXT_SUPPORT 0 #else /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ #define _UITHREADCTXT_SUPPORT 1 #endif /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ #else /* WINAPI_FAMILY */ // Not supported without a WINAPI_FAMILY setting. #define _UITHREADCTXT_SUPPORT 0 #endif /* WINAPI_FAMILY */ #endif /* _UITHREADCTXT_SUPPORT */ #if _UITHREADCTXT_SUPPORT #include
#endif /* _UITHREADCTXT_SUPPORT */ #pragma detect_mismatch("_PPLTASKS_WITH_WINRT", "0") #ifdef _DEBUG #define _DBG_ONLY(X) X #else #define _DBG_ONLY(X) #endif // #ifdef _DEBUG // std::copy_exception changed to std::make_exception_ptr from VS 2010 to VS 11. #ifdef _MSC_VER #if _MSC_VER < 1700 /*IFSTRIP=IGN*/ namespace std { template
exception_ptr make_exception_ptr(_E _Except) { return copy_exception(_Except); } } #endif #ifndef _PPLTASK_ASYNC_LOGGING #if _MSC_VER >= 1800 && defined(__cplusplus_winrt) #define _PPLTASK_ASYNC_LOGGING 1 // Only enable async logging under dev12 winrt #else #define _PPLTASK_ASYNC_LOGGING 0 #endif #endif #endif #pragma pack(push,_CRT_PACKING) #pragma warning(push) #pragma warning(disable: 28197) #pragma warning(disable: 4100) // Unreferenced formal parameter - needed for document generation #if _MSC_VER >= 1800 #pragma warning(disable: 4127) // constant express in if condition - we use it for meta programming #else #pragma warning(disable: 4702) // Unreachable code - it is caused by user lambda throw exceptions #endif // All CRT public header files are required to be protected from the macro new #pragma push_macro("new") #undef new // stuff ported from Dev11 CRT // NOTE: this doesn't actually match std::declval. it behaves differently for void! // so don't blindly change it to std::declval. namespace stdx { template
_T&& declval(); } ///
/// The
Concurrency_winrt
namespace provides classes and functions that give you access to the Concurrency Runtime, /// a concurrent programming framework for C++. For more information, see
. ///
/**/ namespace Concurrency_winrt { // 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. #ifndef PPL_TASK_SAVE_FRAME_COUNT #ifdef _DEBUG #define PPL_TASK_SAVE_FRAME_COUNT 10 #else #define PPL_TASK_SAVE_FRAME_COUNT 1 #endif #endif ///
/// Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 is specified, /// only one frame is captured and no stackwalk will be involved. Otherwise, the number of callstack frames will be captured. ///
///
/// This needs to be defined as a macro rather than a function so that if we're only gathering one frame, _ReturnAddress() /// will evaluate to client code, rather than a helper function inside of _TaskCreationCallstack, itself. /// #ifdef _CAPTURE_CALLSTACK #undef _CAPTURE_CALLSTACK #endif #if PPL_TASK_SAVE_FRAME_COUNT > 1 #if !defined(_DEBUG) #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!") #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress()) #else #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPL_TASK_SAVE_FRAME_COUNT) #endif #else #define _CAPTURE_CALLSTACK() ::Concurrency_winrt::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress()) #endif ///
/// A type that represents the terminal state of a task. Valid values are
completed
and
canceled
. ///
///
/**/ typedef Concurrency::task_group_status task_status; template
class task; template <> class task
; ///
/// Returns an indication of whether the task that is currently executing has received a request to cancel its /// execution. Cancellation is requested on a task if the task was created with a cancellation token, and /// the token source associated with that token is canceled. ///
///
///
true
if the currently executing task has received a request for cancellation,
false
otherwise. ///
///
/// If you call this method in the body of a task and it returns
true
, you must respond with a call to ///
cancel_current_task
to acknowledge the cancellation request, /// after performing any cleanup you need. This will abort the execution of the task and cause it to enter into /// the
canceled
state. If you do not respond and continue execution, or return instead of calling ///
cancel_current_task
, the task will enter the
completed
state when it is done. /// state. ///
A task is not cancellable if it was created without a cancellation token.
///
///
///
///
///
/**/ #if _MSC_VER >= 1800 inline bool __cdecl is_task_cancellation_requested() { return ::Concurrency::details::_TaskCollection_t::_Is_cancellation_requested(); } #else inline bool __cdecl is_task_cancellation_requested() { // ConcRT scheduler under the hood is using TaskCollection, which is same as task_group return ::Concurrency::is_current_task_group_canceling(); } #endif ///
/// Cancels the currently executing task. This function can be called from within the body of a task to abort the /// task's execution and cause it to enter the
canceled
state. While it may be used in response to /// the
is_task_cancellation_requested
function, you may /// also use it by itself, to initiate cancellation of the task that is currently executing. ///
It is not a supported scenario to call this function if you are not within the body of a
task
. /// Doing so will result in undefined behavior such as a crash or a hang in your application.
///
///
///
/**/ //#if _MSC_VER >= 1800 inline __declspec(noreturn) void __cdecl cancel_current_task() { throw Concurrency::task_canceled(); } //#else //_CRTIMP2 __declspec(noreturn) void __cdecl cancel_current_task(); //#endif namespace details { #if _MSC_VER >= 1800 ///
/// Callstack container, which is used to capture and preserve callstacks in ppltasks. /// Members of this class is examined by vc debugger, thus there will be no public access methods. /// Please note that names of this class should be kept stable for debugger examining. ///
class _TaskCreationCallstack { private: // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame; // otherwise, _M_Frame will store all the callstack frames. void* _M_SingleFrame; std::vector
_M_frames; public: _TaskCreationCallstack() { _M_SingleFrame = nullptr; } // Store one frame of callstack. This function works for both Debug / Release CRT. static _TaskCreationCallstack _CaptureSingleFrameCallstack(void *_SingleFrame) { _TaskCreationCallstack _csc; _csc._M_SingleFrame = _SingleFrame; return _csc; } // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT. __declspec(noinline) static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames) { _TaskCreationCallstack _csc; _csc._M_frames.resize(_CaptureFrames); // skip 2 frames to make sure callstack starts from user code _csc._M_frames.resize(::Concurrency::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames)); return _csc; } }; #endif typedef UINT32 _Unit_type; struct _TypeSelectorNoAsync {}; struct _TypeSelectorAsyncOperationOrTask {}; struct _TypeSelectorAsyncOperation : public _TypeSelectorAsyncOperationOrTask { }; struct _TypeSelectorAsyncTask : public _TypeSelectorAsyncOperationOrTask { }; struct _TypeSelectorAsyncAction {}; struct _TypeSelectorAsyncActionWithProgress {}; struct _TypeSelectorAsyncOperationWithProgress {}; template
struct _NormalizeVoidToUnitType { typedef _Ty _Type; }; template<> struct _NormalizeVoidToUnitType
{ typedef _Unit_type _Type; }; template
struct _IsUnwrappedAsyncSelector { static const bool _Value = true; }; template<> struct _IsUnwrappedAsyncSelector<_TypeSelectorNoAsync> { static const bool _Value = false; }; template
struct _UnwrapTaskType { typedef _Ty _Type; }; template
struct _UnwrapTaskType
> { typedef _Ty _Type; }; template
_TypeSelectorAsyncTask _AsyncOperationKindSelector(task<_T>); _TypeSelectorNoAsync _AsyncOperationKindSelector(...); template
struct _Unhat { typedef _Type _Value; }; template
struct _Unhat<_Type*> { typedef _Type _Value; }; //struct _NonUserType { public: int _Dummy; }; template
struct _ValueTypeOrRefType { typedef _Unit_type _Value; }; template
struct _ValueTypeOrRefType<_Type, true> { typedef _Type _Value; }; template
_Ty _UnwrapAsyncActionWithProgressSelector(ABI::Windows::Foundation::IAsyncActionWithProgress_impl<_Ty>*); template
_Ty _UnwrapAsyncActionWithProgressSelector(...); template
_Progress _UnwrapAsyncOperationWithProgressProgressSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<_Ty, _Progress>*); template
_Progress _UnwrapAsyncOperationWithProgressProgressSelector(...); template
_T2 _ProgressTypeSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*); template
_T1 _ProgressTypeSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T1>*); template
struct _GetProgressType { typedef decltype(_ProgressTypeSelector(stdx::declval<_Type>())) _Value; }; template
_TypeSelectorAsyncOperation _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperation<_T>*); _TypeSelectorAsyncAction _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncAction*); template
_TypeSelectorAsyncOperationWithProgress _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*); template
_TypeSelectorAsyncActionWithProgress _AsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T>*); template
struct _IsIAsyncInfo { static const bool _Value = std::is_base_of
::_Value>::value || std::is_same<_TypeSelectorAsyncAction, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value || std::is_same<_TypeSelectorAsyncOperation, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value || std::is_same<_TypeSelectorAsyncOperationWithProgress, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value || std::is_same<_TypeSelectorAsyncActionWithProgress, decltype(details::_AsyncOperationKindSelector(stdx::declval<_Type>()))>::value; }; template <> struct _IsIAsyncInfo
{ static const bool _Value = false; }; template
_Ty _UnwrapAsyncOperationSelector(ABI::Windows::Foundation::IAsyncOperation_impl<_Ty>*); template
_Ty _UnwrapAsyncOperationSelector(...); template
_Ty _UnwrapAsyncOperationWithProgressSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<_Ty, _Progress>*); template
_Ty _UnwrapAsyncOperationWithProgressSelector(...); // Unwrap functions for asyncOperations template
auto _GetUnwrappedType(ABI::Windows::Foundation::IAsyncOperation<_Ty>*) -> typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type; void _GetUnwrappedType(ABI::Windows::Foundation::IAsyncAction*); template
auto _GetUnwrappedType(ABI::Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>*) -> typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type; template
void _GetUnwrappedType(ABI::Windows::Foundation::IAsyncActionWithProgress<_Progress>*); template
_T _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperation<_T>*); void _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncAction*); template
_T1 _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>*); template
void _ReturnAsyncOperationKindSelector(ABI::Windows::Foundation::IAsyncActionWithProgress<_T>*); class _ProgressReporterCtorArgType{}; template
::_Value> struct _TaskTypeTraits { typedef typename details::_UnwrapTaskType<_Type>::_Type _TaskRetType; typedef _TaskRetType _TaskRetType_abi; typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind; typedef typename details::_NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType; static const bool _IsAsyncTask = _IsAsync; static const bool _IsUnwrappedTaskOrAsync = details::_IsUnwrappedAsyncSelector<_AsyncKind>::_Value; }; template
struct _TaskTypeTraits<_Type, true> { typedef decltype(_ReturnAsyncOperationKindSelector(stdx::declval<_Type>())) _TaskRetType; typedef decltype(_GetUnwrappedType(stdx::declval<_Type>())) _TaskRetType_abi; typedef _TaskRetType _NormalizedTaskRetType; typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind; static const bool _IsAsyncTask = true; static const bool _IsUnwrappedTaskOrAsync = details::_IsUnwrappedAsyncSelector<_AsyncKind>::_Value; }; template
auto _IsCallable(_Function _Func, int, int, int) -> decltype(_Func(stdx::declval
*>()), std::true_type()) { (void)_Func; return std::true_type(); } template
auto _IsCallable(_Function _Func, int, int, ...) -> decltype(_Func(stdx::declval<_ReturnType*>()), std::true_type()) { (void)_Func; return std::true_type(); } template
auto _IsCallable(_Function _Func, int, ...) -> decltype(_Func(), std::true_type()) { (void)_Func; return std::true_type(); } template
std::false_type _IsCallable(_Function, ...) { return std::false_type(); } template <> struct _TaskTypeTraits
{ typedef void _TaskRetType; typedef void _TaskRetType_abi; typedef _TypeSelectorNoAsync _AsyncKind; typedef _Unit_type _NormalizedTaskRetType; static const bool _IsAsyncTask = false; static const bool _IsUnwrappedTaskOrAsync = false; }; // *************************************************************************** // Template type traits and helpers for async production APIs: // struct _ZeroArgumentFunctor { }; struct _OneArgumentFunctor { }; struct _TwoArgumentFunctor { }; struct _ThreeArgumentFunctor { }; // **************************************** // CLASS TYPES: // mutable functions // ******************** // THREE ARGUMENTS: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3)); // non-void arg: template
_Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3)); // non-void arg: template
_Arg3 _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3)); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3)); template
_ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3)); // ******************** // TWO ARGUMENTS: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2)); // non-void arg: template
_Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2)); // non-void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2)); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2)); template
_TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2)); // ******************** // ONE ARGUMENT: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1)); // non-void arg: template
void _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1)); // non-void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1)); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1)); template
_OneArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1)); // ******************** // ZERO ARGUMENT: // void arg: template
void _Arg1ClassHelperThunk(_ReturnType(_Class::*)()); // void arg: template
void _Arg2ClassHelperThunk(_ReturnType(_Class::*)()); // void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)()); // void arg: template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)()); template
_ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)()); // ******************** // THREE ARGUMENTS: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const); // non-void arg: template
_Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const); // non-void arg: template
_Arg3 _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const); template
_ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2, _Arg3) const); // ******************** // TWO ARGUMENTS: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const); // non-void arg: template
_Arg2 _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const); // non-void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1, _Arg2) const); template
_TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1, _Arg2) const); // ******************** // ONE ARGUMENT: // non-void arg: template
_Arg1 _Arg1ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const); // non-void arg: template
void _Arg2ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const); // non-void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const); template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)(_Arg1) const); template
_OneArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)(_Arg1) const); // ******************** // ZERO ARGUMENT: // void arg: template
void _Arg1ClassHelperThunk(_ReturnType(_Class::*)() const); // void arg: template
void _Arg2ClassHelperThunk(_ReturnType(_Class::*)() const); // void arg: template
void _Arg3ClassHelperThunk(_ReturnType(_Class::*)() const); // void arg: template
_ReturnType _ReturnTypeClassHelperThunk(_ReturnType(_Class::*)() const); template
_ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(_Class::*)() const); // **************************************** // POINTER TYPES: // ******************** // THREE ARGUMENTS: template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3)); template
_Arg3 _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3)); template
_ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2, _Arg3)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3)); template
_Arg3 _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3)); template
_ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2, _Arg3)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3)); template
_Arg3 _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3)); template
_ThreeArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2, _Arg3)); // ******************** // TWO ARGUMENTS: template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2)); template
void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2)); template
_TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2)); template
void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2)); template
_TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2)); template
_Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2)); template
void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2)); template
_TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2)); // ******************** // ONE ARGUMENT: template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1)); template
void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1)); template
void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1)); template
_OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1)); template
void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1)); template
void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1)); template
_OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1)); template
_Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1)); template
void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1)); template
void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1)); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1)); template
_OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1)); // ******************** // ZERO ARGUMENT: template
void _Arg1PFNHelperThunk(_ReturnType(__cdecl *)()); template
void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)()); template
void _Arg3PFNHelperThunk(_ReturnType(__cdecl *)()); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)()); template
_ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)()); template
void _Arg1PFNHelperThunk(_ReturnType(__stdcall *)()); template
void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)()); template
void _Arg3PFNHelperThunk(_ReturnType(__stdcall *)()); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)()); template
_ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)()); template
void _Arg1PFNHelperThunk(_ReturnType(__fastcall *)()); template
void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)()); template
void _Arg3PFNHelperThunk(_ReturnType(__fastcall *)()); template
_ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)()); template
_ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)()); template
struct _FunctorArguments { static const size_t _Count = 0; }; template<> struct _FunctorArguments<_OneArgumentFunctor> { static const size_t _Count = 1; }; template<> struct _FunctorArguments<_TwoArgumentFunctor> { static const size_t _Count = 2; }; template<> struct _FunctorArguments<_ThreeArgumentFunctor> { static const size_t _Count = 3; }; template
struct _FunctorTypeTraits { typedef decltype(_ArgumentCountHelper(&(_T::operator()))) _ArgumentCountType; static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count; typedef decltype(_ReturnTypeClassHelperThunk(&(_T::operator()))) _ReturnType; typedef decltype(_Arg1ClassHelperThunk(&(_T::operator()))) _Argument1Type; typedef decltype(_Arg2ClassHelperThunk(&(_T::operator()))) _Argument2Type; typedef decltype(_Arg3ClassHelperThunk(&(_T::operator()))) _Argument3Type; }; template
struct _FunctorTypeTraits<_T *> { typedef decltype(_ArgumentCountHelper(stdx::declval<_T*>())) _ArgumentCountType; static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count; typedef decltype(_ReturnTypePFNHelperThunk(stdx::declval<_T*>())) _ReturnType; typedef decltype(_Arg1PFNHelperThunk(stdx::declval<_T*>())) _Argument1Type; typedef decltype(_Arg2PFNHelperThunk(stdx::declval<_T*>())) _Argument2Type; typedef decltype(_Arg3PFNHelperThunk(stdx::declval<_T*>())) _Argument3Type; }; task
_To_task(); template
auto _IsVoidConversionHelper(_Function _Func, int) -> typename decltype(_Func(_To_task()), std::true_type()); template
std::false_type _IsVoidConversionHelper(_Function _Func, ...); template
std::true_type _VoidIsTaskHelper(task
_Arg, int); template
std::false_type _VoidIsTaskHelper(T _Arg, ...); template
(), 0)), std::true_type>::value, const size_t _Count = _FunctorTypeTraits<_Function>::_ArgumentCount> struct _FunctionTypeTraits { typedef typename _Unhat
::_Argument2Type>::_Value _FuncRetType; static_assert(std::is_same
::_Argument1Type, _ExpectedParameterType>::value || std::is_same
::_Argument1Type, task<_ExpectedParameterType>>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)"); typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task; }; //if there is a continuation parameter, then must use void/no return value template
struct _FunctionTypeTraits<_Function, _ExpectedParameterType, _IsVoidConversion, 1> { typedef void _FuncRetType; static_assert(std::is_same
::_Argument1Type, _ExpectedParameterType>::value || std::is_same
::_Argument1Type, task<_ExpectedParameterType>>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)"); typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task; }; template
struct _FunctionTypeTraits<_Function, void, true, 1> { typedef void _FuncRetType; static_assert(std::is_same
::_Argument1Type, decltype(_To_task())>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)"); typedef decltype(_VoidIsTaskHelper(stdx::declval<_FunctorTypeTraits<_Function>::_Argument1Type>(), 0)) _Takes_task; }; template
struct _FunctionTypeTraits<_Function, void, false, 1> { typedef typename _Unhat
::_Argument1Type>::_Value _FuncRetType; typedef std::false_type _Takes_task; }; template
struct _FunctionTypeTraits<_Function, _ExpectedParameterType, _IsVoidConversion, 0> { typedef void _FuncRetType; typedef std::false_type _Takes_task; }; template
struct _ContinuationTypeTraits { typedef typename task
::_FuncRetType>::_TaskRetType_abi> _TaskOfType; }; // _InitFunctorTypeTraits is used to decide whether a task constructed with a lambda should be unwrapped. Depending on how the variable is // declared, the constructor may or may not perform unwrapping. For eg. // // This declaration SHOULD NOT cause unwrapping // task
> t1([]() -> task
{ // task
t2([]() {}); // return t2; // }); // // This declaration SHOULD cause unwrapping // task
> t1([]() -> task
{ // task
t2([]() {}); // return t2; // }); // 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. template
struct _InitFunctorTypeTraits { typedef typename _TaskTypeTraits<_FuncRetType>::_AsyncKind _AsyncKind; static const bool _IsAsyncTask = _TaskTypeTraits<_FuncRetType>::_IsAsyncTask; static const bool _IsUnwrappedTaskOrAsync = _TaskTypeTraits<_FuncRetType>::_IsUnwrappedTaskOrAsync; }; template
struct _InitFunctorTypeTraits
{ typedef _TypeSelectorNoAsync _AsyncKind; static const bool _IsAsyncTask = false; static const bool _IsUnwrappedTaskOrAsync = false; }; ///
/// Helper object used for LWT invocation. ///
struct _TaskProcThunk { _TaskProcThunk(const std::function
& _Callback) : _M_func(_Callback) { } static void __cdecl _Bridge(void *_PData) { _TaskProcThunk *_PThunk = reinterpret_cast<_TaskProcThunk *>(_PData); #if _MSC_VER >= 1800 _Holder _ThunkHolder(_PThunk); #endif _PThunk->_M_func(); #if _MSC_VER < 1800 delete _PThunk; #endif } private: #if _MSC_VER >= 1800 // RAII holder struct _Holder { _Holder(_TaskProcThunk * _PThunk) : _M_pThunk(_PThunk) { } ~_Holder() { delete _M_pThunk; } _TaskProcThunk * _M_pThunk; private: _Holder& operator=(const _Holder&); }; #endif std::function
_M_func; _TaskProcThunk& operator=(const _TaskProcThunk&); }; ///
/// Schedule a functor with automatic inlining. Note that this is "fire and forget" scheduling, which cannot be /// waited on or canceled after scheduling. /// This schedule method will perform automatic inlining base on
. ///
///
/// The user functor need to be scheduled. /// ///
/// The inlining scheduling policy for current functor. /// #if _MSC_VER >= 1800 typedef Concurrency::details::_TaskInliningMode_t _TaskInliningMode; #else typedef Concurrency::details::_TaskInliningMode _TaskInliningMode; #endif static void _ScheduleFuncWithAutoInline(const std::function
& _Func, _TaskInliningMode _InliningMode) { #if _MSC_VER >= 1800 Concurrency::details::_TaskCollection_t::_RunTask(&_TaskProcThunk::_Bridge, new _TaskProcThunk(_Func), _InliningMode); #else Concurrency::details::_StackGuard _Guard; if (_Guard._ShouldInline(_InliningMode)) { _Func(); } else { Concurrency::details::_CurrentScheduler::_ScheduleTask(reinterpret_cast
(&_TaskProcThunk::_Bridge), new _TaskProcThunk(_Func)); } #endif } class _ContextCallback { typedef std::function
_CallbackFunction; public: static _ContextCallback _CaptureCurrent() { _ContextCallback _Context; _Context._Capture(); return _Context; } ~_ContextCallback() { _Reset(); } _ContextCallback(bool _DeferCapture = false) { if (_DeferCapture) { _M_context._M_captureMethod = _S_captureDeferred; } else { _M_context._M_pContextCallback = nullptr; } } // Resolves a context that was created as _S_captureDeferred based on the environment (ancestor, current context). void _Resolve(bool _CaptureCurrent) { if (_M_context._M_captureMethod == _S_captureDeferred) { _M_context._M_pContextCallback = nullptr; if (_CaptureCurrent) { if (_IsCurrentOriginSTA()) { _Capture(); } #if _UITHREADCTXT_SUPPORT else { // This method will fail if not called from the UI thread. HRESULT _Hr = CaptureUiThreadContext(&_M_context._M_pContextCallback); if (FAILED(_Hr)) { _M_context._M_pContextCallback = nullptr; } } #endif // _UITHREADCTXT_SUPPORT } } } void _Capture() { HRESULT _Hr = CoGetObjectContext(IID_IContextCallback, reinterpret_cast
(&_M_context._M_pContextCallback)); if (FAILED(_Hr)) { _M_context._M_pContextCallback = nullptr; } } _ContextCallback(const _ContextCallback& _Src) { _Assign(_Src._M_context._M_pContextCallback); } _ContextCallback(_ContextCallback&& _Src) { _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback; _Src._M_context._M_pContextCallback = nullptr; } _ContextCallback& operator=(const _ContextCallback& _Src) { if (this != &_Src) { _Reset(); _Assign(_Src._M_context._M_pContextCallback); } return *this; } _ContextCallback& operator=(_ContextCallback&& _Src) { if (this != &_Src) { _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback; _Src._M_context._M_pContextCallback = nullptr; } return *this; } bool _HasCapturedContext() const { _CONCRT_ASSERT(_M_context._M_captureMethod != _S_captureDeferred); return (_M_context._M_pContextCallback != nullptr); } HRESULT _CallInContext(_CallbackFunction _Func) const { if (!_HasCapturedContext()) { _Func(); } else { ComCallData callData; ZeroMemory(&callData, sizeof(callData)); callData.pUserDefined = reinterpret_cast
(&_Func); HRESULT _Hr = _M_context._M_pContextCallback->ContextCallback(&_Bridge, &callData, IID_ICallbackWithNoReentrancyToApplicationSTA, 5, nullptr); if (FAILED(_Hr)) { return _Hr; } } return S_OK; } bool operator==(const _ContextCallback& _Rhs) const { return (_M_context._M_pContextCallback == _Rhs._M_context._M_pContextCallback); } bool operator!=(const _ContextCallback& _Rhs) const { return !(operator==(_Rhs)); } private: void _Reset() { if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr) { _M_context._M_pContextCallback->Release(); } } void _Assign(IContextCallback *_PContextCallback) { _M_context._M_pContextCallback = _PContextCallback; if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr) { _M_context._M_pContextCallback->AddRef(); } } static HRESULT __stdcall _Bridge(ComCallData *_PParam) { _CallbackFunction *pFunc = reinterpret_cast<_CallbackFunction *>(_PParam->pUserDefined); return (*pFunc)(); } // Returns the origin information for the caller (runtime / Windows Runtime apartment as far as task continuations need know) static bool _IsCurrentOriginSTA() { APTTYPE _AptType; APTTYPEQUALIFIER _AptTypeQualifier; HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier); if (SUCCEEDED(hr)) { // We determine the origin of a task continuation by looking at where .then is called, so we can tell whether // to need to marshal the continuation back to the originating apartment. If an STA thread is in executing in // a neutral aparment when it schedules a continuation, we will not marshal continuations back to the STA, // since variables used within a neutral apartment are expected to be apartment neutral. switch (_AptType) { case APTTYPE_MAINSTA: case APTTYPE_STA: return true; default: break; } } return false; } union { IContextCallback *_M_pContextCallback; size_t _M_captureMethod; } _M_context; static const size_t _S_captureDeferred = 1; }; #if _MSC_VER >= 1800 template
struct _ResultHolder { void Set(const _Type& _type) { _Result = _type; } _Type Get() { return _Result; } _Type _Result; }; template
struct _ResultHolder<_Type*> { void Set(_Type* const & _type) { _M_Result = _type; } _Type* Get() { return _M_Result.Get(); } private: // ::Platform::Agile handle specialization of all hats // including ::Platform::String and ::Platform::Array Agile<_Type*> _M_Result; }; // // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs. // template
struct _ResultHolder
> { void Set(const std::vector<_Type*>& _type) { _Result.reserve(_type.size()); for (auto _PTask = _type.begin(); _PTask != _type.end(); ++_PTask) { _Result.emplace_back(*_PTask); } } std::vector<_Type*> Get() { // Return vectory
with the objects that are marshaled in the proper appartment std::vector<_Type*> _Return; _Return.reserve(_Result.size()); for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask) { _Return.push_back(_PTask->Get()); // Agile will marshal the object to appropriate appartment if neccessary } return _Return; } std::vector< Agile<_Type*> > _Result; }; template
struct _ResultHolder
> { void Set(const std::pair<_Type*, size_t>& _type) { _M_Result = _type; } std::pair<_Type*, size_t> Get() { return std::make_pair(_M_Result.first, _M_Result.second); } private: std::pair
, size_t> _M_Result; }; #else template
struct _ResultContext { static _ContextCallback _GetContext(bool /* _RuntimeAggregate */) { return _ContextCallback(); } static _Type _GetValue(_Type _ObjInCtx, const _ContextCallback & /* _Ctx */, bool /* _RuntimeAggregate */) { return _ObjInCtx; } }; template
::value> struct _MarshalHelper { }; template
struct _MarshalHelper<_Type, N, true> { static _Type* _Perform(_Type(&_ObjInCtx)[N], const _ContextCallback& _Ctx) { static_assert(__is_valid_winrt_type(_Type*), "must be a WinRT array compatible type"); if (_ObjInCtx == nullptr) { return nullptr; } HRESULT _Hr; IStream * _PStream; _Ctx._CallInContext([&]() -> HRESULT { // It isn't safe to simply reinterpret_cast a hat type to IUnknown* because some types do not have a real vtable ptr. // Instead, we could to create a property value to make it "grow" the vtable ptr but instead primitives are not marshalled. IUnknown * _PUnk = winrt_array_type::create(_ObjInCtx, N); _Hr = CoMarshalInterThreadInterfaceInStream(winrt_type<_Type>::getuuid(), _PUnk, &_PStream); return S_OK; }); // With an APPX manifest, this call should never fail. _CONCRT_ASSERT(SUCCEEDED(_Hr)); _Type* _Proxy; // // Cannot use IID_PPV_ARGS with ^ types. // _Hr = CoGetInterfaceAndReleaseStream(_PStream, winrt_type<_Type>::getuuid(), reinterpret_cast
(&_Proxy)); if (FAILED(_Hr)) { throw std::make_exception_ptr(_Hr); } return _Proxy; } }; template
struct _MarshalHelper<_Type, 0, false> { static _Type* _Perform(_Type* _ObjInCtx, const _ContextCallback& _Ctx) { static_assert(std::is_base_of
::value || __is_valid_winrt_type(_Type), "must be a COM or WinRT type"); if (_ObjInCtx == nullptr) { return nullptr; } HRESULT _Hr; IStream * _PStream; _Ctx._CallInContext([&]() -> HRESULT { // It isn't safe to simply reinterpret_cast a hat type to IUnknown* because some types do not have a real vtable ptr. // Instead, we could to create a property value to make it "grow" the vtable ptr but instead primitives are not marshalled. IUnknown * _PUnk = winrt_type<_Type>::create(_ObjInCtx); _Hr = CoMarshalInterThreadInterfaceInStream(winrt_type<_Type>::getuuid(), _PUnk, &_PStream); return S_OK; }); // With an APPX manifest, this call should never fail. _CONCRT_ASSERT(SUCCEEDED(_Hr)); _Type* _Proxy; // // Cannot use IID_PPV_ARGS with ^ types. // _Hr = CoGetInterfaceAndReleaseStream(_PStream, winrt_type<_Type>::getuuid(), reinterpret_cast
(&_Proxy)); if (FAILED(_Hr)) { throw std::make_exception_ptr(_Hr); } return _Proxy; } }; // Arrays must be converted to IPropertyValue objects. template<> struct _MarshalHelper
{ static HSTRING _Perform(HSTRING _ObjInCtx, const _ContextCallback& _Ctx) { return _ObjInCtx; } }; template
_Type* _Marshal(_Type* _ObjInCtx, const _ContextCallback& _Ctx) { return _MarshalHelper<_Type>::_Perform(_ObjInCtx, _Ctx); } template
struct _InContext { static _Type _Get(_Type _ObjInCtx, const _ContextCallback& _Ctx) { return _ObjInCtx; } }; template
struct _InContext<_Type*> { static _Type* _Get(_Type* _ObjInCtx, const _ContextCallback& _Ctx) { _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent(); if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext) { return _ObjInCtx; } // // The object is from another apartment. If it's marshalable, do so. // return _Marshal<_Type>(_ObjInCtx, _Ctx); } }; template
struct _ResultContext<_Type*> { static _Type* _GetValue(_Type* _ObjInCtx, const _ContextCallback& _Ctx, bool /* _RuntimeAggregate */) { return _InContext<_Type*>::_Get(_ObjInCtx, _Ctx); } static _ContextCallback _GetContext(bool /* _RuntimeAggregate */) { return _ContextCallback::_CaptureCurrent(); } }; // // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs. // template
struct _ResultContext
> { static std::vector<_Type*> _GetValue(std::vector<_Type*> _ObjInCtx, const _ContextCallback& _Ctx, bool _RuntimeAggregate) { if (!_RuntimeAggregate) { return _ObjInCtx; } _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent(); if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext) { return _ObjInCtx; } for (auto _It = _ObjInCtx.begin(); _It != _ObjInCtx.end(); ++_It) { *_It = _Marshal<_Type>(*_It, _Ctx); } return _ObjInCtx; } static _ContextCallback _GetContext(bool _RuntimeAggregate) { if (!_RuntimeAggregate) { return _ContextCallback(); } else { return _ContextCallback::_CaptureCurrent(); } } }; template
struct _ResultContext
> { static std::pair<_Type*, size_t> _GetValue(std::pair<_Type*, size_t> _ObjInCtx, const _ContextCallback& _Ctx, bool _RuntimeAggregate) { if (!_RuntimeAggregate) { return _ObjInCtx; } _ContextCallback _CurrentContext = _ContextCallback::_CaptureCurrent(); if (!_Ctx._HasCapturedContext() || _Ctx == _CurrentContext) { return _ObjInCtx; } return std::pair<_Type*, size_t>(_Marshal<_Type>(_ObjInCtx.first, _Ctx), _ObjInCtx.second); } static _ContextCallback _GetContext(bool _RuntimeAggregate) { if (!_RuntimeAggregate) { return _ContextCallback(); } else { return _ContextCallback::_CaptureCurrent(); } } }; #endif // 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. // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast. struct _ExceptionHolder { #if _MSC_VER >= 1800 private: void ReportUnhandledError() { if (_M_winRTException != nullptr) { throw _M_winRTException.Get(); } } public: explicit _ExceptionHolder(const std::exception_ptr& _E, const _TaskCreationCallstack &_stackTrace) : _M_exceptionObserved(0), _M_stdException(_E), _M_stackTrace(_stackTrace) { } explicit _ExceptionHolder(IRestrictedErrorInfo*& _E, const _TaskCreationCallstack &_stackTrace) : _M_exceptionObserved(0), _M_winRTException(_E), _M_stackTrace(_stackTrace) { } #else explicit _ExceptionHolder(const std::exception_ptr& _E, void* _SourceAddressHint) : _M_exceptionObserved(0), _M_stdException(_E), _M_disassembleMe(_SourceAddressHint) { } explicit _ExceptionHolder(IRestrictedErrorInfo*& _E, void* _SourceAddressHint) : _M_exceptionObserved(0), _M_disassembleMe(_SourceAddressHint), _M_winRTException(_E) { } #endif __declspec(noinline) ~_ExceptionHolder() { if (_M_exceptionObserved == 0) { #if _MSC_VER >= 1800 // If you are trapped here, it means an exception thrown in task chain didn't get handled. // Please add task-based continuation to handle all exceptions coming from tasks. // this->_M_stackTrace keeps the creation callstack of the task generates this exception. _REPORT_PPLTASK_UNOBSERVED_EXCEPTION(); #else // Disassemble at this->_M_disassembleMe to get to the source location right after either the creation of the task (constructor // or then method) that encountered this exception, or the set_exception call for a task_completion_event. Concurrency::details::_ReportUnobservedException(); #endif } } void _RethrowUserException() { if (_M_exceptionObserved == 0) { #if _MSC_VER >= 1800 Concurrency::details::atomic_exchange(_M_exceptionObserved, 1l); #else _InterlockedExchange(&_M_exceptionObserved, 1); #endif } if (_M_winRTException != nullptr) { throw _M_winRTException.Get(); } std::rethrow_exception(_M_stdException); } // A variable that remembers if this exception was every rethrown into user code (and hence handled by the user). Exceptions that // are unobserved when the exception holder is destructed will terminate the process. #if _MSC_VER >= 1800 Concurrency::details::atomic_long _M_exceptionObserved; #else long volatile _M_exceptionObserved; #endif // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered. std::exception_ptr _M_stdException; Microsoft::WRL::ComPtr
_M_winRTException; // Disassembling this value will point to a source instruction right after a call instruction. If the call is to create_task, // a task constructor or the then method, the task created by that method is the one that encountered this exception. If the call // is to task_completion_event::set_exception, the set_exception method was the source of the exception. // DO NOT REMOVE THIS VARIABLE. It is extremely helpful for debugging. #if _MSC_VER >= 1800 _TaskCreationCallstack _M_stackTrace; #else void* _M_disassembleMe; #endif }; #ifndef RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoImpl_DEFINED #define RUNTIMECLASS_Concurrency_winrt_details__AsyncInfoImpl_DEFINED extern const __declspec(selectany) WCHAR RuntimeClass_Concurrency_winrt_details__AsyncInfoImpl[] = L"Concurrency_winrt.details._AsyncInfoImpl"; #endif ///
/// Base converter class for converting asynchronous interfaces to IAsyncOperation ///
template
struct _AsyncInfoImpl abstract : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRt>, Microsoft::WRL::Implements
>> { InspectableClass(RuntimeClass_Concurrency_winrt_details__AsyncInfoImpl, BaseTrust) public: // The async action, action with progress or operation with progress that this stub forwards to. #if _MSC_VER >= 1800 Agile<_AsyncOperationType> _M_asyncInfo; #else Microsoft::WRL::ComPtr<_AsyncOperationType> _M_asyncInfo; // The context in which this async info is valid - may be different from the context where the completion handler runs, // and may require marshalling before it is used. _ContextCallback _M_asyncInfoContext; #endif Microsoft::WRL::ComPtr<_CompletionHandlerType> _M_CompletedHandler; _AsyncInfoImpl(_AsyncOperationType* _AsyncInfo) : _M_asyncInfo(_AsyncInfo) #if _MSC_VER < 1800 , _M_asyncInfoContext(_ContextCallback::_CaptureCurrent()) #endif {} public: virtual HRESULT OnStart() { return S_OK; } virtual void OnCancel() { Microsoft::WRL::ComPtr
pAsyncInfo; HRESULT hr; #if _MSC_VER >= 1800 if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface
(pAsyncInfo.GetAddressOf()))) #else if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo))) #endif pAsyncInfo->Cancel(); else throw std::make_exception_ptr(hr); } virtual void OnClose() { Microsoft::WRL::ComPtr
pAsyncInfo; HRESULT hr; #if _MSC_VER >= 1800 if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface
(pAsyncInfo.GetAddressOf()))) #else if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo))) #endif pAsyncInfo->Close(); else throw std::make_exception_ptr(hr); } virtual STDMETHODIMP get_ErrorCode(HRESULT* errorCode) { Microsoft::WRL::ComPtr
pAsyncInfo; HRESULT hr; #if _MSC_VER >= 1800 if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface
(pAsyncInfo.GetAddressOf()))) #else if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo))) #endif return pAsyncInfo->get_ErrorCode(errorCode); return hr; } virtual STDMETHODIMP get_Id(UINT* id) { Microsoft::WRL::ComPtr
pAsyncInfo; HRESULT hr; #if _MSC_VER >= 1800 if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface
(pAsyncInfo.GetAddressOf()))) #else if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo))) #endif return pAsyncInfo->get_Id(id); return hr; } virtual STDMETHODIMP get_Status(ABI::Windows::Foundation::AsyncStatus *status) { Microsoft::WRL::ComPtr
pAsyncInfo; HRESULT hr; #if _MSC_VER >= 1800 if (SUCCEEDED(hr = _M_asyncInfo.Get()->QueryInterface
(pAsyncInfo.GetAddressOf()))) #else if (SUCCEEDED(hr = _M_asyncInfo.As(&pAsyncInfo))) #endif return pAsyncInfo->get_Status(status); return hr; } virtual STDMETHODIMP GetResults(_Result_abi*) { throw std::runtime_error("derived class must implement"); } virtual STDMETHODIMP get_Completed(_CompletionHandlerType** handler) { if (!handler) return E_POINTER; _M_CompletedHandler.CopyTo(handler); return S_OK; } virtual STDMETHODIMP put_Completed(_CompletionHandlerType* value) { _M_CompletedHandler = value; Microsoft::WRL::ComPtr<_CompletionHandlerType> handler = Microsoft::WRL::Callback<_CompletionHandlerType>([&](_AsyncOperationType*, ABI::Windows::Foundation::AsyncStatus status) -> HRESULT { #if _MSC_VER < 1800 // Update the saved _M_asyncInfo with a proxy valid in the current context if required. Some Windows APIs return an IAsyncInfo // that is only valid for the thread that called the API to retrieve. Since this completion handler can run on any thread, we // need to ensure that the async info is valid in the current apartment. _M_asyncInfo will be accessed via calls to 'this' inside // _AsyncInit. _M_asyncInfo = _ResultContext<_AsyncOperationType*>::_GetValue(_M_asyncInfo.Get(), _M_asyncInfoContext, false); #endif return _M_CompletedHandler->Invoke(_M_asyncInfo.Get(), status); }); #if _MSC_VER >= 1800 return _M_asyncInfo.Get()->put_Completed(handler.Get()); #else return _M_asyncInfo->put_Completed(handler.Get()); #endif } }; extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncOperationToAsyncOperationConverter[] = L"_IAsyncOperationToAsyncOperationConverter"; ///
/// Class _IAsyncOperationToAsyncOperationConverter is used to convert an instance of IAsyncOperationWithProgress
into IAsyncOperation
///
template
struct _IAsyncOperationToAsyncOperationConverter : _AsyncInfoImpl
, ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_Result>, typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type> { typedef typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type _Result_abi; InspectableClass(RuntimeClass_IAsyncOperationToAsyncOperationConverter, BaseTrust) public: _IAsyncOperationToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncOperation<_Result>* _Operation) : _AsyncInfoImpl
, ABI::Windows::Foundation::IAsyncOperationCompletedHandler<_Result>, _Result_abi>(_Operation) {} public: virtual STDMETHODIMP GetResults(_Result_abi* results) override { if (!results) return E_POINTER; #if _MSC_VER >= 1800 return _M_asyncInfo.Get()->GetResults(results); #else return _M_asyncInfo->GetResults(results); #endif } }; extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncOperationWithProgressToAsyncOperationConverter[] = L"_IAsyncOperationWithProgressToAsyncOperationConverter"; ///
/// Class _IAsyncOperationWithProgressToAsyncOperationConverter is used to convert an instance of IAsyncOperationWithProgress
into IAsyncOperation
///
template
struct _IAsyncOperationWithProgressToAsyncOperationConverter : _AsyncInfoImpl
, ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<_Result, _Progress>, typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type> { typedef typename ABI::Windows::Foundation::Internal::GetAbiType
*>()))>::type _Result_abi; InspectableClass(RuntimeClass_IAsyncOperationWithProgressToAsyncOperationConverter, BaseTrust) public: _IAsyncOperationWithProgressToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncOperationWithProgress<_Result, _Progress>* _Operation) : _AsyncInfoImpl
, ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<_Result, _Progress>, _Result_abi>(_Operation) {} public: virtual STDMETHODIMP GetResults(_Result_abi* results) override { if (!results) return E_POINTER; #if _MSC_VER >= 1800 return _M_asyncInfo.Get()->GetResults(results); #else return _M_asyncInfo->GetResults(results); #endif } }; extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncActionToAsyncOperationConverter[] = L"_IAsyncActionToAsyncOperationConverter"; ///
/// Class _IAsyncActionToAsyncOperationConverter is used to convert an instance of IAsyncAction into IAsyncOperation<_Unit_type> ///
struct _IAsyncActionToAsyncOperationConverter : _AsyncInfoImpl
{ InspectableClass(RuntimeClass_IAsyncActionToAsyncOperationConverter, BaseTrust) public: _IAsyncActionToAsyncOperationConverter(ABI::Windows::Foundation::IAsyncAction* _Operation) : _AsyncInfoImpl
(_Operation) {} public: virtual STDMETHODIMP GetResults(details::_Unit_type* results) { if (!results) return E_POINTER; // Invoke GetResults on the IAsyncAction to allow exceptions to be thrown to higher layers before returning a dummy value. #if _MSC_VER >= 1800 HRESULT hr = _M_asyncInfo.Get()->GetResults(); #else HRESULT hr = _M_asyncInfo->GetResults(); #endif if (SUCCEEDED(hr)) *results = _Unit_type(); return hr; } }; extern const __declspec(selectany) WCHAR RuntimeClass_IAsyncActionWithProgressToAsyncOperationConverter[] = L"_IAsyncActionWithProgressToAsyncOperationConverter"; ///