Commit 3c19d0ea authored by Jan Wilken Doerrie's avatar Jan Wilken Doerrie Committed by Commit Bot

[base] Simplify IAsyncOperation Implementation

This change simplifies base/win/async_operation.h by deduplicating logic
and flattening the class hierarchy. This is possible by introducing two
compile time switches, that pick the correct storage and result type
depending on the provided template instantiation.

Bug: 821766
Change-Id: Ia04dc4cdbc42a4005204491cc47650d35f413cdb
Reviewed-on: https://chromium-review.googlesource.com/1106382Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568758}
parent 5eefd62a
......@@ -108,57 +108,46 @@ using LogicalT = typename ABI::Windows::Foundation::Internal::GetLogicalType<
template <typename T>
using InterfaceT = std::remove_pointer_t<AbiT<T>>;
// Implementation of shared functionality.
template <class T>
class AsyncOperationBase
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ABI::Windows::Foundation::IAsyncOperation<T>> {
public:
using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
AsyncOperationBase() = default;
~AsyncOperationBase() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
// ABI::Windows::Foundation::IAsyncOperation:
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);
}
protected:
void InvokeCompletedHandler() {
handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
}
// Compile time switch to decide what container to use for the async results for
// |T|. Depends on whether the underlying Abi type is a pointer to IUnknown or
// not. It queries the internals of Windows::Foundation to obtain this
// information.
template <typename T>
using ResultT =
std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
AbiT<T>>;
THREAD_CHECKER(thread_checker_);
template <typename T>
using StorageT =
std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
base::Optional<AbiT<T>>>;
private:
Microsoft::WRL::ComPtr<Handler> handler_;
template <typename T>
HRESULT CopyStorage(const Microsoft::WRL::ComPtr<T>& storage, T** results) {
return storage.CopyTo(results);
}
DISALLOW_COPY_AND_ASSIGN(AsyncOperationBase);
};
template <typename T>
HRESULT CopyStorage(const base::Optional<T>& storage, T* results) {
*results = *storage;
return S_OK;
}
} // namespace internal
template <typename T, typename Enable = void>
class AsyncOperation;
template <typename T>
class AsyncOperation<
T,
std::enable_if_t<std::is_base_of<IUnknown, internal::InterfaceT<T>>::value>>
: public internal::AsyncOperationBase<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 InterfacePointer = Microsoft::WRL::ComPtr<internal::InterfaceT<T>>;
using ResultCallback = base::OnceCallback<void(InterfacePointer)>;
using StorageT = internal::StorageT<T>;
using ResultT = internal::ResultT<T>;
using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
using ResultCallback = base::OnceCallback<void(ResultT)>;
AsyncOperation() : weak_factory_(this) {
// Note: This can't be done in the constructor initializer list. This is
......@@ -168,74 +157,49 @@ class AsyncOperation<
base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
}
ResultCallback callback() {
// Note: `this->` here and below is necessary due to the
// -Wmicrosoft-template compiler warning.
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
DCHECK(!callback_.is_null());
return std::move(callback_);
}
~AsyncOperation() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
// ABI::Windows::Foundation::IAsyncOperation:
IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
return ptr_ ? ptr_.CopyTo(results) : E_PENDING;
IFACEMETHODIMP put_Completed(Handler* handler) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
handler_ = handler;
return S_OK;
}
private:
void OnResult(InterfacePointer ptr) {
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
DCHECK(!ptr_);
ptr_ = std::move(ptr);
this->InvokeCompletedHandler();
IFACEMETHODIMP get_Completed(Handler** handler) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return handler_.CopyTo(handler);
}
ResultCallback callback_;
InterfacePointer ptr_;
base::WeakPtrFactory<AsyncOperation> weak_factory_;
};
template <typename T>
class AsyncOperation<
T,
std::enable_if_t<
!std::is_base_of<IUnknown, internal::InterfaceT<T>>::value>>
: public internal::AsyncOperationBase<T> {
public:
using ResultCallback = base::OnceCallback<void(T)>;
AsyncOperation() : weak_factory_(this) {
callback_ =
base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return storage_ ? internal::CopyStorage(storage_, results) : E_PENDING;
}
ResultCallback callback() {
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!callback_.is_null());
return std::move(callback_);
}
// ABI::Windows::Foundation::IAsyncOperation:
IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
if (!value_)
return E_PENDING;
*results = *value_;
return S_OK;
private:
void InvokeCompletedHandler() {
handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
}
private:
void OnResult(T result) {
DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
DCHECK(!value_);
value_.emplace(std::move(result));
this->InvokeCompletedHandler();
void OnResult(ResultT result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!storage_);
storage_ = std::move(result);
InvokeCompletedHandler();
}
ResultCallback callback_;
base::Optional<T> value_;
Microsoft::WRL::ComPtr<Handler> handler_;
StorageT storage_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<AsyncOperation> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AsyncOperation);
};
} // namespace win
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment