diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 3804d3401c..d8071c269a 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4504,8 +4504,8 @@ int predictOptimalVectorWidth(InputArray src1, InputArray src2, InputArray src3, if (vectorWidths[0] == 1) { // it's heuristic - vectorWidths[CV_8U] = vectorWidths[CV_8S] = 16; - vectorWidths[CV_16U] = vectorWidths[CV_16S] = 8; + vectorWidths[CV_8U] = vectorWidths[CV_8S] = 4; + vectorWidths[CV_16U] = vectorWidths[CV_16S] = 2; vectorWidths[CV_32S] = vectorWidths[CV_32F] = vectorWidths[CV_64F] = 1; } diff --git a/modules/highgui/src/agile_wrl.h b/modules/highgui/src/agile_wrl.h new file mode 100644 index 0000000000..99fbf41856 --- /dev/null +++ b/modules/highgui/src/agile_wrl.h @@ -0,0 +1,568 @@ +// +// Copyright (C) Microsoft Corporation +// All rights reserved. +// Modified for native C++ WRL support by Gregory Morse +// +// Code in Details namespace is for internal usage within the library code +// + +#ifndef _PLATFORM_AGILE_H_ +#define _PLATFORM_AGILE_H_ + +#ifdef _MSC_VER +#pragma once +#endif // _MSC_VER + +#include +#include + +template class Agile; + +template +struct UnwrapAgile +{ + static const bool _IsAgile = false; +}; +template +struct UnwrapAgile> +{ + static const bool _IsAgile = true; +}; +template +struct UnwrapAgile> +{ + static const bool _IsAgile = true; +}; + +#define IS_AGILE(T) UnwrapAgile::_IsAgile + +#define __is_winrt_agile(T) (std::is_same::value || std::is_base_of::value || std::is_base_of::value) //derived from Microsoft::WRL::FtmBase or IAgileObject + +#define __is_win_interface(T) (std::is_base_of::value || std::is_base_of::value) //derived from IUnknown or IInspectable + +#define __is_win_class(T) (std::is_same::value || std::is_base_of::value) //derived from Microsoft::WRL::RuntimeClass or HSTRING + + namespace Details + { + IUnknown* __stdcall GetObjectContext(); + HRESULT __stdcall GetProxyImpl(IUnknown*, REFIID, IUnknown*, IUnknown**); + HRESULT __stdcall ReleaseInContextImpl(IUnknown*, IUnknown*); + + template +#if _MSC_VER >= 1800 + __declspec(no_refcount) inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) +#else + inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) +#endif + { +#if _MSC_VER >= 1800 + return GetProxyImpl(*reinterpret_cast(&ObjectIn), __uuidof(T*), ContextCallBack, reinterpret_cast(Proxy)); +#else + return GetProxyImpl(*reinterpret_cast(&const_cast(ObjectIn)), __uuidof(T*), ContextCallBack, reinterpret_cast(Proxy)); +#endif + } + + template + inline HRESULT ReleaseInContext(T *ObjectIn, IUnknown *ContextCallBack) + { + return ReleaseInContextImpl(ObjectIn, ContextCallBack); + } + + template + class AgileHelper + { + __abi_IUnknown* _p; + bool _release; + public: + AgileHelper(__abi_IUnknown* p, bool release = true) : _p(p), _release(release) + { + } + AgileHelper(AgileHelper&& other) : _p(other._p), _release(other._release) + { + _other._p = nullptr; + _other._release = true; + } + AgileHelper operator=(AgileHelper&& other) + { + _p = other._p; + _release = other._release; + _other._p = nullptr; + _other._release = true; + return *this; + } + + ~AgileHelper() + { + if (_release && _p) + { + _p->__abi_Release(); + } + } + + __declspec(no_refcount) __declspec(no_release_return) + T* operator->() + { + return reinterpret_cast(_p); + } + + __declspec(no_refcount) __declspec(no_release_return) + operator T * () + { + return reinterpret_cast(_p); + } + private: + AgileHelper(const AgileHelper&); + AgileHelper operator=(const AgileHelper&); + }; + template + struct __remove_hat + { + typedef T type; + }; + template + struct __remove_hat + { + typedef T type; + }; + template + struct AgileTypeHelper + { + typename typedef __remove_hat::type type; + typename typedef __remove_hat::type* agileMemberType; + }; + } // namespace Details + +#pragma warning(push) +#pragma warning(disable: 4451) // Usage of ref class inside this context can lead to invalid marshaling of object across contexts + + template < + typename T, + bool TIsNotAgile = (__is_win_class(typename Details::AgileTypeHelper::type) && !__is_winrt_agile(typename Details::AgileTypeHelper::type)) || + __is_win_interface(typename Details::AgileTypeHelper::type) + > + class Agile + { + static_assert(__is_win_class(typename Details::AgileTypeHelper::type) || __is_win_interface(typename Details::AgileTypeHelper::type), "Agile can only be used with ref class or interface class types"); + typename typedef Details::AgileTypeHelper::agileMemberType TypeT; + TypeT _object; + ::Microsoft::WRL::ComPtr _contextCallback; + ULONG_PTR _contextToken; + +#if _MSC_VER >= 1800 + enum class AgileState + { + NonAgilePointer = 0, + AgilePointer = 1, + Unknown = 2 + }; + AgileState _agileState; +#endif + + void CaptureContext() + { + _contextCallback = Details::GetObjectContext(); + __abi_ThrowIfFailed(CoGetContextToken(&_contextToken)); + } + + void SetObject(TypeT object) + { + // Capture context before setting the pointer + // If context capture fails then nothing to cleanup + Release(); + if (object != nullptr) + { + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); + // Don't Capture context if object is agile + if (hr != S_OK) + { +#if _MSC_VER >= 1800 + _agileState = AgileState::NonAgilePointer; +#endif + CaptureContext(); + } +#if _MSC_VER >= 1800 + else + { + _agileState = AgileState::AgilePointer; + } +#endif + } + _object = object; + } + + public: + Agile() throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + } + + Agile(nullptr_t) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + } + + explicit Agile(TypeT object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Assumes that the source object is from the current context + SetObject(object); + } + + Agile(const Agile& object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Get returns pointer valid for current context + SetObject(object.Get()); + } + + Agile(Agile&& object) throw() : _object(nullptr), _contextToken(0) +#if _MSC_VER >= 1800 + , _agileState(AgileState::Unknown) +#endif + { + // Assumes that the source object is from the current context + Swap(object); + } + + ~Agile() throw() + { + Release(); + } + + TypeT Get() const + { + // Agile object, no proxy required +#if _MSC_VER >= 1800 + if (_agileState == AgileState::AgilePointer || _object == nullptr) +#else + if (_contextToken == 0 || _contextCallback == nullptr || _object == nullptr) +#endif + { + return _object; + } + + // Do the check for same context + ULONG_PTR currentContextToken; + __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); + if (currentContextToken == _contextToken) + { + return _object; + } + +#if _MSC_VER >= 1800 + // Different context and holding on to a non agile object + // Do the costly work of getting a proxy + TypeT localObject; + __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); + + if (_agileState == AgileState::Unknown) +#else + // Object is agile if it implements IAgileObject + // GetAddressOf captures the context with out knowing the type of object that it will hold + if (_object != nullptr) +#endif + { +#if _MSC_VER >= 1800 + // Object is agile if it implements IAgileObject + // GetAddressOf captures the context with out knowing the type of object that it will hold + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(localObject)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); +#else + ::Microsoft::WRL::ComPtr checkIfAgile; + HRESULT hr = reinterpret_cast(_object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); +#endif + if (hr == S_OK) + { + auto pThis = const_cast(this); +#if _MSC_VER >= 1800 + pThis->_agileState = AgileState::AgilePointer; +#endif + pThis->_contextToken = 0; + pThis->_contextCallback = nullptr; + return _object; + } +#if _MSC_VER >= 1800 + else + { + auto pThis = const_cast(this); + pThis->_agileState = AgileState::NonAgilePointer; + } +#endif + } + +#if _MSC_VER < 1800 + // Different context and holding on to a non agile object + // Do the costly work of getting a proxy + TypeT localObject; + __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); +#endif + return localObject; + } + + TypeT* GetAddressOf() throw() + { + Release(); + CaptureContext(); + return &_object; + } + + TypeT* GetAddressOfForInOut() throw() + { + CaptureContext(); + return &_object; + } + + TypeT operator->() const throw() + { + return Get(); + } + + Agile& operator=(nullptr_t) throw() + { + Release(); + return *this; + } + + Agile& operator=(TypeT object) throw() + { + Agile(object).Swap(*this); + return *this; + } + + Agile& operator=(Agile object) throw() + { + // parameter is by copy which gets pointer valid for current context + object.Swap(*this); + return *this; + } + +#if _MSC_VER < 1800 + Agile& operator=(IUnknown* lp) throw() + { + // bump ref count + ::Microsoft::WRL::ComPtr spObject(lp); + + // put it into Platform Object + Platform::Object object; + *(IUnknown**)(&object) = spObject.Detach(); + + SetObject(object); + return *this; + } +#endif + + void Swap(Agile& object) + { + std::swap(_object, object._object); + std::swap(_contextCallback, object._contextCallback); + std::swap(_contextToken, object._contextToken); +#if _MSC_VER >= 1800 + std::swap(_agileState, object._agileState); +#endif + } + + // Release the interface and set to NULL + void Release() throw() + { + if (_object) + { + // Cast to IInspectable (no QI) + IUnknown* pObject = *(IUnknown**)(&_object); + // Set * to null without release + *(IUnknown**)(&_object) = nullptr; + + ULONG_PTR currentContextToken; + __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); + if (_contextToken == 0 || _contextCallback == nullptr || _contextToken == currentContextToken) + { + pObject->Release(); + } + else + { + Details::ReleaseInContext(pObject, _contextCallback.Get()); + } + _contextCallback = nullptr; + _contextToken = 0; +#if _MSC_VER >= 1800 + _agileState = AgileState::Unknown; +#endif + } + } + + bool operator==(nullptr_t) const throw() + { + return _object == nullptr; + } + + bool operator==(const Agile& other) const throw() + { + return _object == other._object && _contextToken == other._contextToken; + } + + bool operator<(const Agile& other) const throw() + { + if (reinterpret_cast(_object) < reinterpret_cast(other._object)) + { + return true; + } + + return _object == other._object && _contextToken < other._contextToken; + } + }; + + template + class Agile + { + static_assert(__is_win_class(typename Details::AgileTypeHelper::type) || __is_win_interface(typename Details::AgileTypeHelper::type), "Agile can only be used with ref class or interface class types"); + typename typedef Details::AgileTypeHelper::agileMemberType TypeT; + TypeT _object; + + public: + Agile() throw() : _object(nullptr) + { + } + + Agile(nullptr_t) throw() : _object(nullptr) + { + } + + explicit Agile(TypeT object) throw() : _object(object) + { + } + + Agile(const Agile& object) throw() : _object(object._object) + { + } + + Agile(Agile&& object) throw() : _object(nullptr) + { + Swap(object); + } + + ~Agile() throw() + { + Release(); + } + + TypeT Get() const + { + return _object; + } + + TypeT* GetAddressOf() throw() + { + Release(); + return &_object; + } + + TypeT* GetAddressOfForInOut() throw() + { + return &_object; + } + + TypeT operator->() const throw() + { + return Get(); + } + + Agile& operator=(nullptr_t) throw() + { + Release(); + return *this; + } + + Agile& operator=(TypeT object) throw() + { + if (_object != object) + { + _object = object; + } + return *this; + } + + Agile& operator=(Agile object) throw() + { + object.Swap(*this); + return *this; + } + +#if _MSC_VER < 1800 + Agile& operator=(IUnknown* lp) throw() + { + Release(); + // bump ref count + ::Microsoft::WRL::ComPtr spObject(lp); + + // put it into Platform Object + Platform::Object object; + *(IUnknown**)(&object) = spObject.Detach(); + + _object = object; + return *this; + } +#endif + + // Release the interface and set to NULL + void Release() throw() + { + _object = nullptr; + } + + void Swap(Agile& object) + { + std::swap(_object, object._object); + } + + bool operator==(nullptr_t) const throw() + { + return _object == nullptr; + } + + bool operator==(const Agile& other) const throw() + { + return _object == other._object; + } + + bool operator<(const Agile& other) const throw() + { + return reinterpret_cast(_object) < reinterpret_cast(other._object); + } + }; + +#pragma warning(pop) + + template + bool operator==(nullptr_t, const Agile& a) throw() + { + return a == nullptr; + } + + template + bool operator!=(const Agile& a, nullptr_t) throw() + { + return !(a == nullptr); + } + + template + bool operator!=(nullptr_t, const Agile& a) throw() + { + return !(a == nullptr); + } + + template + bool operator!=(const Agile& a, const Agile& b) throw() + { + return !(a == b); + } + + +#endif // _PLATFORM_AGILE_H_ diff --git a/modules/highgui/src/ppltasks_winrt.h b/modules/highgui/src/ppltasks_winrt.h index 29dccbd70b..1243baea97 100644 --- a/modules/highgui/src/ppltasks_winrt.h +++ b/modules/highgui/src/ppltasks_winrt.h @@ -17,24 +17,44 @@ #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 +#ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/ // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user #include @@ -45,72 +65,72 @@ #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 +#else /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ #define _UITHREADCTXT_SUPPORT 1 -#endif +#endif /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */ -#else +#else /* WINAPI_FAMILY */ // Not supported without a WINAPI_FAMILY setting. #define _UITHREADCTXT_SUPPORT 0 -#endif // #ifdef WINAPI_FAMILY +#endif /* WINAPI_FAMILY */ -#endif // #ifndef _UITHREADCTXT_SUPPORT +#endif /* _UITHREADCTXT_SUPPORT */ #if _UITHREADCTXT_SUPPORT #include -#endif // _UITHREADCTXT_SUPPORT +#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 -#define __is_valid_winrt_type(_Type) (std::is_void<_Type>::value || \ - std::is_same<_Type, BYTE>::value || \ - std::is_same<_Type, INT16>::value || \ - std::is_same<_Type, UINT16>::value || \ - std::is_same<_Type, INT32>::value || \ - std::is_same<_Type, UINT32>::value || \ - std::is_same<_Type, INT64>::value || \ - std::is_same<_Type, UINT64>::value || \ - std::is_same<_Type, FLOAT>::value || \ - std::is_same<_Type, DOUBLE>::value || \ - std::is_same<_Type, WCHAR>::value || \ - std::is_same<_Type, boolean>::value || \ - std::is_same<_Type, HSTRING>::value || \ - std::is_same<_Type, IInspectable *>::value || \ - std::is_same<_Type, GUID>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::DateTime>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::TimeSpan>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Point>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Size>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Rect>::value || \ - std::is_same<_Type, BYTE*>::value || \ - std::is_same<_Type, INT16*>::value || \ - std::is_same<_Type, UINT16*>::value || \ - std::is_same<_Type, INT32*>::value || \ - std::is_same<_Type, UINT32*>::value || \ - std::is_same<_Type, INT64*>::value || \ - std::is_same<_Type, UINT64*>::value || \ - std::is_same<_Type, FLOAT*>::value || \ - std::is_same<_Type, DOUBLE*>::value || \ - std::is_same<_Type, WCHAR*>::value || \ - std::is_same<_Type, boolean*>::value || \ - std::is_same<_Type, HSTRING*>::value || \ - std::is_same<_Type, IInspectable **>::value || \ - std::is_same<_Type, GUID*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::DateTime*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::TimeSpan*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Point*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Size*>::value || \ - std::is_same<_Type, ABI::Windows::Foundation::Rect*>::value) +// 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, @@ -119,7 +139,38 @@ /**/ 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. /// /// @@ -151,7 +202,18 @@ template <> class task; /// /// /**/ -_CRTIMP2 bool __cdecl is_task_cancellation_requested(); +#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 @@ -164,10 +226,56 @@ _CRTIMP2 bool __cdecl is_task_cancellation_requested(); /// /// /**/ -_CRTIMP2 __declspec(noreturn) void __cdecl cancel_current_task(); +//#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 {}; @@ -231,12 +339,12 @@ namespace details typedef _Type _Value; }; - struct _NonUserType { public: int _Dummy; }; + //struct _NonUserType { public: int _Dummy; }; template struct _ValueTypeOrRefType { - typedef _NonUserType _Value; + typedef _Unit_type _Value; }; template @@ -245,6 +353,18 @@ namespace details 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>*); @@ -254,42 +374,7 @@ namespace details template struct _GetProgressType { - typedef decltype(_ProgressTypeSelector(std::declval<_Type>())) _Value; - }; - - template