SynchronousOperation.h 4.7 KB

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