123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- #ifndef BASE_WIN_POST_ASYNC_RESULTS_H_
- #define BASE_WIN_POST_ASYNC_RESULTS_H_
- #include <unknwn.h>
- #include <windows.foundation.h>
- #include <wrl/async.h>
- #include <wrl/client.h>
- #include <type_traits>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/location.h"
- #include "base/logging.h"
- #include "base/threading/thread_task_runner_handle.h"
- namespace base {
- namespace win {
- namespace internal {
- constexpr const char* ToCString(AsyncStatus async_status) {
- switch (async_status) {
- case AsyncStatus::Started:
- return "AsyncStatus::Started";
- case AsyncStatus::Completed:
- return "AsyncStatus::Completed";
- case AsyncStatus::Canceled:
- return "AsyncStatus::Canceled";
- case AsyncStatus::Error:
- return "AsyncStatus::Error";
- }
- NOTREACHED();
- return "";
- }
- template <typename T>
- using AsyncAbiT = typename ABI::Windows::Foundation::Internal::GetAbiType<
- typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex>::
- type;
- template <typename T>
- using AsyncResultsT = std::conditional_t<
- std::is_convertible<AsyncAbiT<T>, IUnknown*>::value,
- Microsoft::WRL::ComPtr<std::remove_pointer_t<AsyncAbiT<T>>>,
- AsyncAbiT<T>>;
- template <typename T>
- AsyncResultsT<T> GetAsyncResults(
- ABI::Windows::Foundation::IAsyncOperation<T>* async_op) {
- AsyncResultsT<T> results;
- HRESULT hr = async_op->GetResults(&results);
- if (FAILED(hr)) {
- VLOG(2) << "GetAsyncResults failed: "
- << logging::SystemErrorCodeToString(hr);
- return AsyncResultsT<T>{};
- }
- return results;
- }
- }
- template <typename T>
- HRESULT PostAsyncResults(
- Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<T>>
- async_op,
- base::OnceCallback<void(internal::AsyncResultsT<T>)> callback) {
- auto completed_cb = base::BindOnce(
- [](Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<T>>
- async_op,
- base::OnceCallback<void(internal::AsyncResultsT<T>)> callback) {
- std::move(callback).Run(internal::GetAsyncResults(async_op.Get()));
- },
- async_op, std::move(callback));
- auto completed_lambda = [task_runner(base::ThreadTaskRunnerHandle::Get()),
- completed_cb(std::move(completed_cb))](
- auto&&, AsyncStatus async_status) mutable {
- if (async_status != AsyncStatus::Completed) {
- VLOG(2) << "Got unexpected AsyncStatus: "
- << internal::ToCString(async_status);
- }
-
-
-
-
-
- task_runner->PostTask(FROM_HERE, std::move(completed_cb));
- return S_OK;
- };
- using CompletedHandler = Microsoft::WRL::Implements<
- Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
- ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>,
- Microsoft::WRL::FtmBase>;
- return async_op->put_Completed(
- Microsoft::WRL::Callback<CompletedHandler>(std::move(completed_lambda))
- .Get());
- }
- }
- }
- #endif
|