Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef BASE_SEQUENCE_TOKEN_H_ |
| 6 | #define BASE_SEQUENCE_TOKEN_H_ |
| 7 | |
| 8 | #include "base/base_export.h" |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 9 | |
François Doray | 2bd91ed | 2024-02-16 15:30:45 | [diff] [blame] | 10 | namespace base { |
| 11 | namespace internal { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 12 | |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 13 | // A token that identifies a series of sequenced work items (i.e. tasks, native |
| 14 | // message handlers, code blocks running outside or a `RunLoop`, etc. that are |
| 15 | // mutually exclusive). |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 16 | class BASE_EXPORT SequenceToken { |
| 17 | public: |
| 18 | // Instantiates an invalid SequenceToken. |
Peter Kasting | 960e2d3 | 2023-03-14 17:18:41 | [diff] [blame] | 19 | constexpr SequenceToken() = default; |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 20 | |
| 21 | // Explicitly allow copy. |
| 22 | SequenceToken(const SequenceToken& other) = default; |
| 23 | SequenceToken& operator=(const SequenceToken& other) = default; |
| 24 | |
| 25 | // An invalid SequenceToken is not equal to any other SequenceToken, including |
| 26 | // other invalid SequenceTokens. |
| 27 | bool operator==(const SequenceToken& other) const; |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 28 | |
| 29 | // Returns true if this is a valid SequenceToken. |
| 30 | bool IsValid() const; |
| 31 | |
gab | b755507 | 2016-10-06 21:16:24 | [diff] [blame] | 32 | // Returns the integer uniquely representing this SequenceToken. This method |
| 33 | // should only be used for tracing and debugging. |
| 34 | int ToInternalValue() const; |
| 35 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 36 | // Returns a valid SequenceToken which isn't equal to any previously returned |
| 37 | // SequenceToken. |
| 38 | static SequenceToken Create(); |
| 39 | |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 40 | // Returns the `SequenceToken` for the work item currently running on this |
| 41 | // thread. A valid and unique `SequenceToken` is assigned to each thread. It |
| 42 | // can be overridden in a scope with `TaskScope`. |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 43 | static SequenceToken GetForCurrentThread(); |
| 44 | |
| 45 | private: |
gab | aa8b597 | 2016-08-10 02:46:47 | [diff] [blame] | 46 | explicit SequenceToken(int token) : token_(token) {} |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 47 | |
| 48 | static constexpr int kInvalidSequenceToken = -1; |
| 49 | int token_ = kInvalidSequenceToken; |
| 50 | }; |
| 51 | |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 52 | // A token that identifies a task. |
| 53 | // |
| 54 | // This is used by ThreadCheckerImpl to determine whether calls to |
| 55 | // CalledOnValidThread() come from the same task and hence are deterministically |
| 56 | // single-threaded (vs. calls coming from different sequenced or parallel tasks, |
| 57 | // which may or may not run on the same thread). |
| 58 | class BASE_EXPORT TaskToken { |
| 59 | public: |
| 60 | // Instantiates an invalid TaskToken. |
Peter Kasting | 960e2d3 | 2023-03-14 17:18:41 | [diff] [blame] | 61 | constexpr TaskToken() = default; |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 62 | |
| 63 | // Explicitly allow copy. |
| 64 | TaskToken(const TaskToken& other) = default; |
| 65 | TaskToken& operator=(const TaskToken& other) = default; |
| 66 | |
| 67 | // An invalid TaskToken is not equal to any other TaskToken, including |
| 68 | // other invalid TaskTokens. |
| 69 | bool operator==(const TaskToken& other) const; |
| 70 | bool operator!=(const TaskToken& other) const; |
| 71 | |
| 72 | // Returns true if this is a valid TaskToken. |
| 73 | bool IsValid() const; |
| 74 | |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 75 | // In the scope of a `TaskScope`, returns a valid `TaskToken` which isn't |
| 76 | // equal to any `TaskToken` returned in the scope of a different `TaskScope`. |
| 77 | // Otherwise, returns an invalid `TaskToken`. |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 78 | static TaskToken GetForCurrentThread(); |
| 79 | |
| 80 | private: |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 81 | friend class TaskScope; |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 82 | |
gab | aa8b597 | 2016-08-10 02:46:47 | [diff] [blame] | 83 | explicit TaskToken(int token) : token_(token) {} |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 84 | |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 85 | // Returns a valid `TaskToken` which isn't equal to any previously returned |
| 86 | // `TaskToken`. Private as it is only meant to be instantiated by `TaskScope`. |
fdoray | b339954b | 2016-08-09 21:49:26 | [diff] [blame] | 87 | static TaskToken Create(); |
| 88 | |
| 89 | static constexpr int kInvalidTaskToken = -1; |
| 90 | int token_ = kInvalidTaskToken; |
| 91 | }; |
| 92 | |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 93 | // Returns true if a thread checker bound in a different task than the current |
| 94 | // one but on the same sequence and thread may return true from |
| 95 | // `CalledOnValidSequence()`. |
| 96 | bool BASE_EXPORT CurrentTaskIsThreadBound(); |
| 97 | |
| 98 | // Identifies a scope in which a task runs. |
| 99 | class BASE_EXPORT [[maybe_unused, nodiscard]] TaskScope { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 100 | public: |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 101 | // `sequence_token` identifies the series of mutually exclusive work items |
| 102 | // that this task is part of (may be unique if this task isn't mutually |
| 103 | // exclusive with any other work item). `is_thread_bound` sets the value |
| 104 | // returned by `CurrentTaskIsThreadBound()` within the scope. |
François Doray | 2bd91ed | 2024-02-16 15:30:45 | [diff] [blame] | 105 | // `is_running_synchronously` is true iff this is instantiated for a task run |
| 106 | // synchronously by `RunOrPostTask()`. |
Lei Zhang | b39481fd | 2025-06-26 01:03:40 | [diff] [blame] | 107 | TaskScope(SequenceToken sequence_token, |
| 108 | bool is_thread_bound, |
| 109 | bool is_running_synchronously = false); |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 110 | TaskScope(const TaskScope&) = delete; |
| 111 | TaskScope& operator=(const TaskScope&) = delete; |
| 112 | ~TaskScope(); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 113 | |
| 114 | private: |
François Doray | 524d2a2 | 2024-01-04 09:54:16 | [diff] [blame] | 115 | const TaskToken previous_task_token_; |
| 116 | const SequenceToken previous_sequence_token_; |
| 117 | const bool previous_task_is_thread_bound_; |
François Doray | 2bd91ed | 2024-02-16 15:30:45 | [diff] [blame] | 118 | const bool previous_task_is_running_synchronously_; |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 119 | }; |
| 120 | |
François Doray | 2bd91ed | 2024-02-16 15:30:45 | [diff] [blame] | 121 | } // namespace internal |
| 122 | |
| 123 | // Returns true if the current task is run synchronously by `RunOrPostTask()`. |
| 124 | bool BASE_EXPORT CurrentTaskIsRunningSynchronously(); |
| 125 | |
| 126 | } // namespace base |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 127 | |
| 128 | #endif // BASE_SEQUENCE_TOKEN_H_ |