v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
waiter-queue-node.cc
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
6
7#include "src/base/macros.h"
10
11namespace v8 {
12namespace internal {
13namespace detail {
14
15WaiterQueueNode::WaiterQueueNode(Isolate* requester) : requester_(requester) {}
16
18 // Since waiter queue nodes are allocated on the stack, they must be removed
19 // from the intrusive linked list once they go out of scope, otherwise there
20 // will be dangling pointers.
22}
23
24// static
26 WaiterQueueNode* new_tail) {
27 DCHECK_NOT_NULL(head);
28 new_tail->VerifyNotInList();
29 WaiterQueueNode* current_head = *head;
30 if (current_head == nullptr) {
31 new_tail->next_ = new_tail;
32 new_tail->prev_ = new_tail;
33 *head = new_tail;
34 } else {
35 WaiterQueueNode* current_tail = current_head->prev_;
36 current_tail->next_ = new_tail;
37 current_head->prev_ = new_tail;
38 new_tail->next_ = current_head;
39 new_tail->prev_ = current_tail;
40 }
41}
42
44 if (next_ == this) {
45 // The queue contains exactly 1 node.
46 *head = nullptr;
47 } else {
48 // The queue contains >1 nodes.
49 if (this == *head) {
50 WaiterQueueNode* tail = (*head)->prev_;
51 // The matched node is the head, so next is the new head.
52 next_->prev_ = tail;
53 tail->next_ = next_;
54 *head = next_;
55 } else {
56 // The matched node is in the middle of the queue, so the head does
57 // not need to be updated.
58 prev_->next_ = next_;
59 next_->prev_ = prev_;
60 }
61 }
63}
64
66 WaiterQueueNode** head, const DequeueMatcher& matcher) {
67 DCHECK_NOT_NULL(head);
68 DCHECK_NOT_NULL(*head);
69 WaiterQueueNode* original_head = *head;
70 WaiterQueueNode* cur = *head;
71 do {
72 if (matcher(cur)) {
73 cur->DequeueUnchecked(head);
74 return cur;
75 }
76 cur = cur->next_;
77 } while (cur != original_head);
78 return nullptr;
79}
80
82 WaiterQueueNode** head, const DequeueMatcher& matcher) {
83 DCHECK_NOT_NULL(head);
84 DCHECK_NOT_NULL(*head);
85 WaiterQueueNode* original_tail = (*head)->prev_;
86 WaiterQueueNode* cur = *head;
87 for (;;) {
88 DCHECK_NOT_NULL(cur);
89 WaiterQueueNode* next = cur->next_;
90 if (matcher(cur)) {
91 cur->DequeueUnchecked(head);
93 }
94 if (cur == original_tail) break;
95 cur = next;
96 }
97}
98
99// static
101 return DequeueMatching(head, [](WaiterQueueNode* node) { return true; });
102}
103
104// static
106 uint32_t count) {
107 DCHECK_GT(count, 0);
108 DCHECK_NOT_NULL(head);
109 DCHECK_NOT_NULL(*head);
110 WaiterQueueNode* front_head = *head;
111 WaiterQueueNode* back_head = front_head;
112 uint32_t actual_count = 0;
113 while (actual_count < count) {
114 back_head = back_head->next_;
115 // The queue is shorter than the requested count, return the whole queue.
116 if (back_head == front_head) {
117 *head = nullptr;
118 return front_head;
119 }
120 actual_count++;
121 }
122 WaiterQueueNode* front_tail = back_head->prev_;
123 WaiterQueueNode* back_tail = front_head->prev_;
124
125 // Fix up the back list (i.e. remainder of the list).
126 back_head->prev_ = back_tail;
127 back_tail->next_ = back_head;
128 *head = back_head;
129
130 // Fix up and return the front list (i.e. the dequeued list).
131 front_head->prev_ = front_tail;
132 front_tail->next_ = front_head;
133 return front_head;
134}
135
136// static
138 WaiterQueueNode* cur = head;
139 int len = 0;
140 do {
141 len++;
142 cur = cur->next_;
143 } while (cur != head);
144 return len;
145}
146
148 WaiterQueueNode* cur = this;
149 uint32_t count = 0;
150 do {
151 WaiterQueueNode* next = cur->next_;
152 cur->Notify();
153 cur = next;
154 count++;
155 } while (cur != this);
156 return count;
157}
158
163
165#ifdef DEBUG
166 next_ = prev_ = nullptr;
167#endif
168}
169
170} // namespace detail
171} // namespace internal
172} // namespace v8
static void DequeueAllMatchingForAsyncCleanup(WaiterQueueNode **head, const DequeueMatcher &matcher)
std::function< bool(WaiterQueueNode *)> DequeueMatcher
static void Enqueue(WaiterQueueNode **head, WaiterQueueNode *new_tail)
static int LengthFromHead(WaiterQueueNode *head)
void DequeueUnchecked(WaiterQueueNode **head)
static WaiterQueueNode * Dequeue(WaiterQueueNode **head)
static WaiterQueueNode * DequeueMatching(WaiterQueueNode **head, const DequeueMatcher &matcher)
static WaiterQueueNode * Split(WaiterQueueNode **head, uint32_t count)
uint32_t count
#define DCHECK_NULL(val)
Definition logging.h:491
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GT(v1, v2)
Definition logging.h:487