#ifndef BASE_WIN_ASYNC_OPERATION_H_
#define BASE_WIN_ASYNC_OPERATION_H_
#include <unknwn.h>
#include <windows.foundation.h>
#include <wrl/async.h>
#include <wrl/client.h>
#include <type_traits>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/win/winrt_foundation_helpers.h"
namespace base {
namespace win {
namespace internal {
template <typename T>
using AsyncOperationComplex =
typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
template <typename T>
using AsyncOperationAbi = AbiType<AsyncOperationComplex<T>>;
template <typename T>
using AsyncOperationOptionalStorage =
OptionalStorageType<AsyncOperationComplex<T>>;
template <typename T>
using AsyncOperationStorage = StorageType<AsyncOperationComplex<T>>;
}
template <class T>
class AsyncOperation
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ABI::Windows::Foundation::IAsyncOperation<T>> {
public:
using AbiT = internal::AsyncOperationAbi<T>;
using OptionalStorageT = internal::AsyncOperationOptionalStorage<T>;
using StorageT = internal::AsyncOperationStorage<T>;
using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
using ResultCallback = base::OnceCallback<void(StorageT)>;
AsyncOperation() {
callback_ =
base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
}
AsyncOperation(const AsyncOperation&) = delete;
AsyncOperation& operator=(const AsyncOperation&) = delete;
~AsyncOperation() override { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
IFACEMETHODIMP put_Completed(Handler* handler) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
handler_ = handler;
return S_OK;
}
IFACEMETHODIMP get_Completed(Handler** handler) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return handler_.CopyTo(handler);
}
IFACEMETHODIMP GetResults(AbiT* results) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return results_ ? internal::CopyTo(results_, results) : E_PENDING;
}
ResultCallback callback() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!callback_.is_null());
return std::move(callback_);
}
private:
void InvokeCompletedHandler() {
handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
}
void OnResult(StorageT result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!results_);
results_ = std::move(result);
InvokeCompletedHandler();
}
ResultCallback callback_;
Microsoft::WRL::ComPtr<Handler> handler_;
OptionalStorageT results_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<AsyncOperation> weak_factory_{this};
};
}
}
#endif