File: cross_thread_functional.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (113 lines) | stat: -rw-r--r-- 4,462 bytes parent folder | download | duplicates (5)
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_