async_operation.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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/memory/weak_ptr.h"
  15. #include "base/threading/thread_checker.h"
  16. #include "base/win/winrt_foundation_helpers.h"
  17. namespace base {
  18. namespace win {
  19. // This file provides an implementation of Windows::Foundation::IAsyncOperation.
  20. // Specializations exist for "regular" types and interface types that inherit
  21. // from IUnknown. Both specializations expose a callback() method, which can be
  22. // used to provide the result that will be forwarded to the registered
  23. // completion handler. For regular types it expects an instance of that type,
  24. // and for interface types it expects a corresponding ComPtr. This class is
  25. // thread-affine and all member methods should be called on the same thread that
  26. // constructed the object. In order to offload heavy result computation,
  27. // base's PostTaskAndReplyWithResult() should be used with the ResultCallback
  28. // passed as a reply.
  29. //
  30. // Example usages:
  31. //
  32. // // Regular types
  33. // auto regular_op = WRL::Make<base::win::AsyncOperation<int>>();
  34. // auto cb = regular_op->callback();
  35. // regular_op->put_Completed(...event handler...);
  36. // ...
  37. // // This will invoke the event handler.
  38. // std::move(cb).Run(123);
  39. // ...
  40. // // Results can be queried:
  41. // int results = 0;
  42. // regular_op->GetResults(&results);
  43. // EXPECT_EQ(123, results);
  44. //
  45. // // Interface types
  46. // auto interface_op = WRL::Make<base::win::AsyncOperation<FooBar*>>();
  47. // auto cb = interface_op->callback();
  48. // interface_op->put_Completed(...event handler...);
  49. // ...
  50. // // This will invoke the event handler.
  51. // std::move(cb).Run(WRL::Make<IFooBarImpl>());
  52. // ...
  53. // // Results can be queried:
  54. // WRL::ComPtr<IFooBar> results;
  55. // interface_op->GetResults(&results);
  56. // // |results| points to the provided IFooBarImpl instance.
  57. //
  58. // // Offloading a heavy computation:
  59. // auto my_op = WRL::Make<base::win::AsyncOperation<FooBar*>>();
  60. // base::PostTaskAndReplyWithResult(
  61. // base::BindOnce(MakeFooBar), my_op->callback());
  62. namespace internal {
  63. // Template tricks needed to dispatch to the correct implementation below.
  64. // See base/win/winrt_foundation_helpers.h for explanation.
  65. template <typename T>
  66. using AsyncOperationComplex =
  67. typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
  68. template <typename T>
  69. using AsyncOperationAbi = AbiType<AsyncOperationComplex<T>>;
  70. template <typename T>
  71. using AsyncOperationOptionalStorage =
  72. OptionalStorageType<AsyncOperationComplex<T>>;
  73. template <typename T>
  74. using AsyncOperationStorage = StorageType<AsyncOperationComplex<T>>;
  75. } // namespace internal
  76. template <class T>
  77. class AsyncOperation
  78. : public Microsoft::WRL::RuntimeClass<
  79. Microsoft::WRL::RuntimeClassFlags<
  80. Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
  81. ABI::Windows::Foundation::IAsyncOperation<T>> {
  82. public:
  83. using AbiT = internal::AsyncOperationAbi<T>;
  84. using OptionalStorageT = internal::AsyncOperationOptionalStorage<T>;
  85. using StorageT = internal::AsyncOperationStorage<T>;
  86. using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
  87. using ResultCallback = base::OnceCallback<void(StorageT)>;
  88. AsyncOperation() {
  89. // Note: This can't be done in the constructor initializer list. This is
  90. // because it relies on weak_factory_ to be initialized, which needs to be
  91. // the last class member. Also applies below.
  92. callback_ =
  93. base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
  94. }
  95. AsyncOperation(const AsyncOperation&) = delete;
  96. AsyncOperation& operator=(const AsyncOperation&) = delete;
  97. ~AsyncOperation() override { 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. };
  133. } // namespace win
  134. } // namespace base
  135. #endif // BASE_WIN_ASYNC_OPERATION_H_