1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CROSS_THREAD_FUNCTIONAL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CROSS_THREAD_FUNCTIONAL_H_
#include <type_traits>
#include "base/functional/bind.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace WTF {
// `CrossThreadBindOnce()` and `CrossThreadBindRepeating()` are the Blink
// equivalents of `base::BindOnce()` and `base::BindRepeating()` for creating
// a callback that is run or destroyed on a different thread.
//
// Unlike `base::RepeatingCallback`, a repeatable cross-thread function is *not*
// copyable. This is intentional: a number of objects in Blink are
// thread-hostile: allowing a cross-thread function to be copied
// means it would be easy to end up in situations where multiple threads might
// unsafely reference the same object.
//
// TODO(crbug.com/963574): Deprecate `CrossThreadBindRepeating()`.
//
// Example:
// // Given the prototype:
// // void MyFunction(const ThreadUnsafeObject&, int);
// ThreadUnsafeObject obj;
// CrossThreadFunction<void(int)> f =
// CrossThreadBindOnce(&MyFunction, obj);
// std::move(f).Run(42); // Calls MyFunction(<deep copy of `obj`>, 42);
//
// Arguments bound to a `CrossThreadFunction` are copied with
// `CrossThreadCopier`.
//
// Important!
// `CrossThreadBindOnce(obj)` is similar to `BindOnce(<deep copy of `obj`>)`,
// but historically, the latter was unsafe since it was possible to end up with
// situations where a thread-hostile object would be referenced on multiple
// threads, leading to crashes. See https://crbug.com/390851 for more details.
//
// In contrast, `CrossThreadBindOnce()` and `CrossThreadBindRepeating()` are
// implemented in a way that only the destination thread can refer to any bound
// arguments.
namespace internal {
template <typename Signature>
auto MakeCrossThreadFunction(base::RepeatingCallback<Signature> callback) {
return CrossThreadFunction<Signature>(std::move(callback));
}
template <typename Signature>
auto MakeCrossThreadOnceFunction(base::OnceCallback<Signature> callback) {
return CrossThreadOnceFunction<Signature>(std::move(callback));
}
// Insertion of coercion for specific types; transparent forwarding otherwise.
template <typename T>
decltype(auto) CoerceFunctorForCrossThreadBind(T&& functor) {
return std::forward<T>(functor);
}
template <typename Signature>
base::RepeatingCallback<Signature> CoerceFunctorForCrossThreadBind(
CrossThreadFunction<Signature>&& functor) {
return ConvertToBaseRepeatingCallback(std::move(functor));
}
template <typename Signature>
base::OnceCallback<Signature> CoerceFunctorForCrossThreadBind(
CrossThreadOnceFunction<Signature>&& functor) {
return ConvertToBaseOnceCallback(std::move(functor));
}
} // namespace internal
template <typename FunctionType, typename... Ps>
auto CrossThreadBindRepeating(FunctionType&& function, Ps&&... parameters) {
static_assert(
internal::CheckGCedTypeRestrictions<std::index_sequence_for<Ps...>,
std::decay_t<Ps>...>::ok,
"A bound argument uses a bad pattern.");
return internal::MakeCrossThreadFunction(
base::BindRepeating(internal::CoerceFunctorForCrossThreadBind(
std::forward<FunctionType>(function)),
CrossThreadCopier<std::decay_t<Ps>>::Copy(
std::forward<Ps>(parameters))...));
}
template <typename FunctionType, typename... Ps>
auto CrossThreadBindOnce(FunctionType&& function, Ps&&... parameters) {
static_assert(
internal::CheckGCedTypeRestrictions<std::index_sequence_for<Ps...>,
std::decay_t<Ps>...>::ok,
"A bound argument uses a bad pattern.");
return internal::MakeCrossThreadOnceFunction(
base::BindOnce(internal::CoerceFunctorForCrossThreadBind(
std::forward<FunctionType>(function)),
CrossThreadCopier<std::decay_t<Ps>>::Copy(
std::forward<Ps>(parameters))...));
}
} // namespace WTF
using WTF::CrossThreadBindOnce;
using WTF::CrossThreadBindRepeating;
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CROSS_THREAD_FUNCTIONAL_H_
|