SynchronousOperation.h
4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once
#include "ReferenceCounter.h"
#include "os/Win32/WindowsHeaders.h"
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
#include <wrl.h>
#include <vector>
namespace il2cpp
{
namespace winrt
{
template<typename T>
struct ResultTypeTraits
{
typedef typename ABI::Windows::Foundation::Internal::GetLogicalType<typename T::TResult_complex>::type LogicalType;
typedef typename ABI::Windows::Foundation::Internal::GetAbiType<typename T::TResult_complex>::type ResultType;
};
template<>
struct ResultTypeTraits<ABI::Windows::Foundation::IAsyncAction>
{
typedef void LogicalType;
typedef void ResultType;
};
template<typename OperationType, typename HandlerType>
class SynchronousOperationBase : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>, Microsoft::WRL::FtmBase, HandlerType>
{
protected:
HANDLE m_Event;
HRESULT m_HR;
typedef OperationType OperationType;
inline SynchronousOperationBase(OperationType* op)
{
m_Event = CreateEventExW(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
Assert(m_Event && "CreateEventExW failed.");
}
inline ~SynchronousOperationBase()
{
CloseHandle(m_Event);
// This will be not 0 if it's allocated on the stack
// This class must be allocated on the heap for correct COM ref counting!
IL2CPP_ASSERT(GetRefCount() == 0);
}
public:
inline HRESULT Wait()
{
auto waitResult = WaitForSingleObjectEx(m_Event, INFINITE, FALSE);
if (waitResult != WAIT_OBJECT_0)
return E_FAIL;
return m_HR;
}
};
template<typename T>
class SynchronousOperation : public SynchronousOperationBase<ABI::Windows::Foundation::IAsyncOperation<T>, ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T> >
{
private:
typedef typename ResultTypeTraits<OperationType>::ResultType ResultType;
ResultType m_Result;
public:
inline SynchronousOperation(OperationType* op) :
SynchronousOperationBase(op),
m_Result(ResultType())
{
// NOTE: this is in the derived class because it might immediately complete.
// If this was called from the base class, you'd get a callback on a partially
// constructed vtable and crash.
auto hr = op->put_Completed(this);
Assert(SUCCEEDED(hr) && "IAsyncOperation<T>::put_Completed failed.");
}
~SynchronousOperation()
{
ReferenceCounter<ResultType>::Release(m_Result);
}
HRESULT GetResults(ResultType* result)
{
auto hr = Wait();
if (FAILED(hr))
return hr;
*result = m_Result;
ReferenceCounter<ResultType>::AddRef(*result);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Invoke(ABI::Windows::Foundation::IAsyncOperation<T>* asyncInfo, ABI::Windows::Foundation::AsyncStatus status) override
{
m_HR = asyncInfo->GetResults(&m_Result);
SetEvent(m_Event);
return S_OK;
}
static Microsoft::WRL::ComPtr<SynchronousOperation<T> > Make(OperationType* op)
{
return Microsoft::WRL::Make<SynchronousOperation<T> >(op);
}
};
template<>
class SynchronousOperation<void> : public SynchronousOperationBase<ABI::Windows::Foundation::IAsyncAction, ABI::Windows::Foundation::IAsyncActionCompletedHandler>
{
public:
inline SynchronousOperation(OperationType* op) :
SynchronousOperationBase(op)
{
// NOTE: this is in the derived class because it might immediately complete.
// If this was called from the base class, you'd get a callback on a partially
// constructed vtable and crash.
auto hr = op->put_Completed(this);
Assert(SUCCEEDED(hr) && "IAsyncAction::put_Completed failed.");
}
virtual HRESULT STDMETHODCALLTYPE Invoke(ABI::Windows::Foundation::IAsyncAction* asyncInfo, ABI::Windows::Foundation::AsyncStatus status) override
{
m_HR = asyncInfo->GetResults();
SetEvent(m_Event);
return S_OK;
}
};
template<typename T>
Microsoft::WRL::ComPtr<SynchronousOperation<typename ResultTypeTraits<T>::LogicalType> > MakeSynchronousOperation(T* op)
{
return Microsoft::WRL::Make<SynchronousOperation<typename ResultTypeTraits<T>::LogicalType> >(op);
}
}
}