Commit d9e35229 authored by Yuta Kitamura's avatar Yuta Kitamura Committed by Commit Bot

Move out threading DCHECK from WTF::Function.

This patch is largely based on tzik's WIP patch:
https://chromium-review.googlesource.com/c/chromium/src/+/742824

Bug: 771087
Change-Id: I20e2eb5ef09911a19e3b268e45ce6187d8edeffa
Reviewed-on: https://chromium-review.googlesource.com/765749
Commit-Queue: Yuta Kitamura <yutak@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarTaiju Tsuiki <tzik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517030}
parent e99ca27b
...@@ -210,6 +210,77 @@ struct CheckGCedTypeRestrictions<std::index_sequence<Ns...>, Args...> ...@@ -210,6 +210,77 @@ struct CheckGCedTypeRestrictions<std::index_sequence<Ns...>, Args...>
} // namespace internal } // namespace internal
#if DCHECK_IS_ON()
template <typename CallbackType,
typename RunType = typename CallbackType::RunType>
class ThreadCheckingCallbackWrapper;
// This class wraps a callback and applies thread checking on its construction,
// destruction and invocation (on Run()).
template <typename CallbackType, typename R, typename... Args>
class ThreadCheckingCallbackWrapper<CallbackType, R(Args...)> {
public:
explicit ThreadCheckingCallbackWrapper(CallbackType callback)
: callback_(std::move(callback)) {}
~ThreadCheckingCallbackWrapper() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
R Run(Args... args) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return RunInternal(&callback_, std::forward<Args>(args)...);
}
bool IsCancelled() const { return callback_.IsCancelled(); }
private:
static R RunInternal(base::RepeatingCallback<R(Args...)>* callback,
Args&&... args) {
return callback->Run(std::forward<Args>(args)...);
}
static R RunInternal(base::OnceCallback<R(Args...)>* callback,
Args&&... args) {
return std::move(*callback).Run(std::forward<Args>(args)...);
}
SEQUENCE_CHECKER(sequence_checker_);
CallbackType callback_;
DISALLOW_COPY_AND_ASSIGN(ThreadCheckingCallbackWrapper);
};
} // namespace WTF
namespace base {
template <typename CallbackType,
typename R,
typename... Args,
typename... BoundArgs>
struct CallbackCancellationTraits<
R (WTF::ThreadCheckingCallbackWrapper<CallbackType>::*)(Args...),
std::tuple<
std::unique_ptr<WTF::ThreadCheckingCallbackWrapper<CallbackType>>,
BoundArgs...>> {
static constexpr bool is_cancellable = true;
template <typename Functor, typename Receiver, typename... RunArgs>
static bool IsCancelled(const Functor&,
const Receiver& receiver,
const RunArgs&...) {
return receiver->IsCancelled();
}
};
} // namespace base
namespace WTF {
#endif
template <typename Signature> template <typename Signature>
class Function; class Function;
...@@ -221,32 +292,23 @@ class Function<R(Args...)> { ...@@ -221,32 +292,23 @@ class Function<R(Args...)> {
Function() {} Function() {}
explicit Function(base::Callback<R(Args...)> callback) explicit Function(base::Callback<R(Args...)> callback)
: callback_(std::move(callback)) {} : callback_(std::move(callback)) {}
~Function() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } ~Function() {}
Function(const Function&) = delete; Function(const Function&) = delete;
Function& operator=(const Function&) = delete; Function& operator=(const Function&) = delete;
Function(Function&& other) : callback_(std::move(other.callback_)) { Function(Function&& other) : callback_(std::move(other.callback_)) {}
DCHECK_CALLED_ON_VALID_THREAD(other.thread_checker_);
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DETACH_FROM_THREAD(other.thread_checker_);
}
Function& operator=(Function&& other) { Function& operator=(Function&& other) {
DCHECK_CALLED_ON_VALID_THREAD(other.thread_checker_);
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DETACH_FROM_THREAD(other.thread_checker_);
callback_ = std::move(other.callback_); callback_ = std::move(other.callback_);
return *this; return *this;
} }
R Run(Args... args) const & { R Run(Args... args) const & {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return callback_.Run(std::forward<Args>(args)...); return callback_.Run(std::forward<Args>(args)...);
} }
R Run(Args... args) && { R Run(Args... args) && {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return std::move(callback_).Run(std::forward<Args>(args)...); return std::move(callback_).Run(std::forward<Args>(args)...);
} }
...@@ -259,7 +321,6 @@ class Function<R(Args...)> { ...@@ -259,7 +321,6 @@ class Function<R(Args...)> {
} }
private: private:
THREAD_CHECKER(thread_checker_);
base::Callback<R(Args...)> callback_; base::Callback<R(Args...)> callback_;
}; };
...@@ -313,8 +374,15 @@ Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>> Bind( ...@@ -313,8 +374,15 @@ Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>> Bind(
"A bound argument uses a bad pattern."); "A bound argument uses a bad pattern.");
using UnboundRunType = using UnboundRunType =
base::MakeUnboundRunType<FunctionType, BoundParameters...>; base::MakeUnboundRunType<FunctionType, BoundParameters...>;
return Function<UnboundRunType>( auto cb =
base::Bind(function, std::forward<BoundParameters>(bound_parameters)...)); base::Bind(function, std::forward<BoundParameters>(bound_parameters)...);
#if DCHECK_IS_ON()
using WrapperType =
ThreadCheckingCallbackWrapper<base::Callback<UnboundRunType>>;
cb = base::Bind(&WrapperType::Run,
std::make_unique<WrapperType>(std::move(cb)));
#endif
return Function<UnboundRunType>(std::move(cb));
} }
// TODO(tzik): Replace WTF::Function with base::OnceCallback, and // TODO(tzik): Replace WTF::Function with base::OnceCallback, and
......
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