v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
waiter-queue-node.h
Go to the documentation of this file.
1// Copyright 2024 the V8 project authors. All rights reserved.
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 V8_OBJECTS_WAITER_QUEUE_NODE_H_
6#define V8_OBJECTS_WAITER_QUEUE_NODE_H_
7
9
10namespace v8 {
11
12namespace base {
13class TimeDelta;
14} // namespace base
15
16namespace internal {
17
18class Context;
19class Isolate;
20template <typename T>
21class Tagged;
22
23namespace detail {
24
25// To manage waiting threads inside JSSynchronizationPrimitives, there is a
26// process-wide doubly-linked intrusive list per waiter (i.e. mutex or condition
27// variable). There is a per-thread node allocated on the stack when the thread
28// goes to sleep for synchronous locking and waiting, and a per-call node
29// allocated on the C++ heap for asynchronous locking and waiting.
30//
31// When compressing pointers (including when sandboxing), the access to the
32// node is indirected through the shared external pointer table.
33//
34// The WaiterQueueNode is an abstract class encapsulting the general queue
35// logic (enqueue, dequeue, etc...). Its extensions add the logic to handle
36// notifications and sync/async waiting.
37// TODO(v8:12547): Unittest this.
39 public:
40 virtual ~WaiterQueueNode();
41
42 // Enqueues {new_tail}, mutating {head} to be the new head.
43 static void Enqueue(WaiterQueueNode** head, WaiterQueueNode* new_tail);
44
45 using DequeueMatcher = std::function<bool(WaiterQueueNode*)>;
46 // Dequeues the first waiter for which {matcher} returns true and returns it;
47 // mutating {head} to be the new head.
48 //
49 // The queue lock must be held in the synchronization primitive that owns
50 // this waiter queue when calling this method.
51 static WaiterQueueNode* DequeueMatching(WaiterQueueNode** head,
52 const DequeueMatcher& matcher);
53
54 static void DequeueAllMatchingForAsyncCleanup(WaiterQueueNode** head,
55 const DequeueMatcher& matcher);
56
57 static WaiterQueueNode* Dequeue(WaiterQueueNode** head);
58
59 // Splits at most {count} nodes of the waiter list of into its own list and
60 // returns it, mutating {head} to be the head of the back list.
61 static WaiterQueueNode* Split(WaiterQueueNode** head, uint32_t count);
62
63 // This method must be called from a known waiter queue head. Incorrectly
64 // encoded lists can cause this method to infinitely loop.
65 static int LengthFromHead(WaiterQueueNode* head);
66
67 uint32_t NotifyAllInList();
68
69 virtual void Notify() = 0;
70
71 // Async cleanup functions.
72 virtual bool IsSameIsolateForAsyncCleanup(Isolate* isolate) = 0;
73 virtual void CleanupMatchingAsyncWaiters(const DequeueMatcher& matcher) = 0;
74
75 protected:
76 explicit WaiterQueueNode(Isolate* requester);
77
78 void SetNotInListForVerification();
79
80 virtual void SetReadyForAsyncCleanup() = 0;
81
83 // The queue wraps around, e.g. the head's prev is the tail, and the tail's
84 // next is the head.
85 WaiterQueueNode* next_ = nullptr;
87
88 private:
89 void DequeueUnchecked(WaiterQueueNode** head);
90 void VerifyNotInList();
91};
92
93} // namespace detail
94} // namespace internal
95} // namespace v8
96
97#endif // V8_OBJECTS_WAITER_QUEUE_NODE_H_
virtual bool IsSameIsolateForAsyncCleanup(Isolate *isolate)=0
std::function< bool(WaiterQueueNode *)> DequeueMatcher
virtual void CleanupMatchingAsyncWaiters(const DequeueMatcher &matcher)=0
Node * prev_
#define V8_NODISCARD
Definition v8config.h:693