async_operation.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_WIN_ASYNC_OPERATION_H_
  5. #define BASE_WIN_ASYNC_OPERATION_H_
  6. #include <unknwn.h>
  7. #include <windows.foundation.h>
  8. #include <wrl/async.h>
  9. #include <wrl/client.h>
  10. #include <type_traits>
  11. #include <utility>
  12. #include "base/bind.h"
  13. #include "base/callback.h"
  14. #include "base/macros.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/optional.h"
  17. #include "base/threading/thread_checker.h"
  18. #include "base/win/winrt_foundation_helpers.h"
  19. namespace base {
  20. namespace win {
  21. // This file provides an implementation of Windows::Foundation::IAsyncOperation.
  22. // Specializations exist for "regular" types and interface types that inherit
  23. // from IUnknown. Both specializations expose a callback() method, which can be
  24. // used to provide the result that will be forwarded to the registered
  25. // completion handler. For regular types it expects an instance of that type,
  26. // and for interface types it expects a corresponding ComPtr. This class is
  27. // thread-affine and all member methods should be called on the same thread that
  28. // constructed the object. In order to offload heavy result computation,
  29. // base's PostTaskAndReplyWithResult() should be used with the ResultCallback
  30. // passed as a reply.
  31. //
  32. // Example usages:
  33. //
  34. // // Regular types
  35. // auto regular_op = WRL::Make<base::win::AsyncOperation<int>>();
  36. // auto cb = regular_op->callback();
  37. // regular_op->put_Completed(...event handler...);
  38. // ...
  39. // // This will invoke the event handler.
  40. // std::move(cb).Run(123);
  41. // ...
  42. // // Results can be queried:
  43. // int results = 0;
  44. // regular_op->GetResults(&results);
  45. // EXPECT_EQ(123, results);
  46. //
  47. // // Interface types
  48. // auto interface_op = WRL::Make<base::win::AsyncOperation<FooBar*>>();
  49. // auto cb = interface_op->callback();
  50. // interface_op->put_Completed(...event handler...);
  51. // ...
  52. // // This will invoke the event handler.
  53. // std::move(cb).Run(WRL::Make<IFooBarImpl>());
  54. // ...
  55. // // Results can be queried:
  56. // WRL::ComPtr<IFooBar> results;
  57. // interface_op->GetResults(&results);
  58. // // |results| points to the provided IFooBarImpl instance.
  59. //
  60. // // Offloading a heavy computation:
  61. // auto my_op = WRL::Make<base::win::AsyncOperation<FooBar*>>();
  62. // base::PostTaskAndReplyWithResult(
  63. // base::BindOnce(MakeFooBar), my_op->callback());
  64. namespace internal {
  65. // Template tricks needed to dispatch to the correct implementation below.
  66. // See base/win/winrt_foundation_helpers.h for explanation.
  67. template <typename T>
  68. using AsyncOperationComplex =
  69. typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
  70. template <typename T>
  71. using AsyncOperationAbi = AbiType<AsyncOperationComplex<T>>;
  72. template <typename T>
  73. using AsyncOperationOptionalStorage =
  74. OptionalStorageType<AsyncOperationComplex<T>>;
  75. template <typename T>
  76. using AsyncOperationStorage = StorageType<AsyncOperationComplex<T>>;
  77. } // namespace internal
  78. template <class T>
  79. class AsyncOperation
  80. : public Microsoft::WRL::RuntimeClass<
  81. Microsoft::WRL::RuntimeClassFlags<
  82. Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
  83. ABI::Windows::Foundation::IAsyncOperation<T>> {
  84. public:
  85. using AbiT = internal::AsyncOperationAbi<T>;
  86. using OptionalStorageT = internal::AsyncOperationOptionalStorage<T>;
  87. using StorageT = internal::AsyncOperationStorage<T>;
  88. using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
  89. using ResultCallback = base::OnceCallback<void(StorageT)>;
  90. AsyncOperation() {
  91. // Note: This can't be done in the constructor initializer list. This is
  92. // because it relies on weak_factory_ to be initialized, which needs to be
  93. // the last class member. Also applies below.
  94. callback_ =
  95. base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
  96. }
  97. ~AsyncOperation() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
  98. // ABI::Windows::Foundation::IAsyncOperation:
  99. IFACEMETHODIMP put_Completed(Handler* handler) override {
  100. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  101. handler_ = handler;
  102. return S_OK;
  103. }
  104. IFACEMETHODIMP get_Completed(Handler** handler) override {
  105. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  106. return handler_.CopyTo(handler);
  107. }
  108. IFACEMETHODIMP GetResults(AbiT* results) override {
  109. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  110. return results_ ? internal::CopyTo(results_, results) : E_PENDING;
  111. }
  112. ResultCallback callback() {
  113. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  114. DCHECK(!callback_.is_null());
  115. return std::move(callback_);
  116. }
  117. private:
  118. void InvokeCompletedHandler() {
  119. handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
  120. }
  121. void OnResult(StorageT result) {
  122. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  123. DCHECK(!results_);
  124. results_ = std::move(result);
  125. InvokeCompletedHandler();
  126. }
  127. ResultCallback callback_;
  128. Microsoft::WRL::ComPtr<Handler> handler_;
  129. OptionalStorageT results_;
  130. THREAD_CHECKER(thread_checker_);
  131. base::WeakPtrFactory<AsyncOperation> weak_factory_{this};
  132. DISALLOW_COPY_AND_ASSIGN(AsyncOperation);
  133. };
  134. } // namespace win
  135. } // namespace base
  136. #endif // BASE_WIN_ASYNC_OPERATION_H_