/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/objects/waiter-queue-node.cc
196 строк
6 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// Copyright 2024 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/objects/waiter-queue-node.h" #include "src/base/macros.h" #include "src/base/platform/time.h" #include "src/heap/local-heap-inl.h" namespace v8 { namespace internal { namespace detail { WaiterQueueNode::WaiterQueueNode(Isolate* requester) : requester_(requester), should_wait_(true) {} WaiterQueueNode::~WaiterQueueNode() { // Since waiter queue nodes are allocated on the stack, they must be removed // from the intrusive linked list once they go out of scope, otherwise there // will be dangling pointers. SbxCheckNotInList(); } // static void WaiterQueueNode::Enqueue(WaiterQueueNode** head, WaiterQueueNode* new_tail) { DCHECK_NOT_NULL(head); new_tail->SbxCheckNotInList(); WaiterQueueNode* current_head = *head; if (current_head == nullptr) { new_tail->next_ = new_tail; new_tail->prev_ = new_tail; *head = new_tail; } else { WaiterQueueNode* current_tail = current_head->prev_; current_tail->next_ = new_tail; current_head->prev_ = new_tail; new_tail->next_ = current_head; new_tail->prev_ = current_tail; } } WaiterQueueNode* WaiterQueueNode::DequeueMatching( WaiterQueueNode** head, const DequeueMatcher& matcher) { DCHECK_NOT_NULL(head); DCHECK_NOT_NULL(*head); WaiterQueueNode* const original_head = *head; WaiterQueueNode* cur = *head; do { if (matcher(cur)) { WaiterQueueNode* const next = cur->next_; if (next == cur) { // The queue contains exactly 1 node. DCHECK_EQ(cur, original_head); *head = nullptr; } else { // The queue contains >1 nodes. if (cur == original_head) { // The matched node is the original head, so next is the new head. WaiterQueueNode* tail = original_head->prev_; next->prev_ = tail; tail->next_ = next; *head = next; } else { // The matched node is in the middle of the queue, so the head does // not need to be updated. cur->prev_->next_ = next; next->prev_ = cur->prev_; } } cur->SetNotInListForVerification(); return cur; } cur = cur->next_; } while (cur != original_head); return nullptr; } // static WaiterQueueNode* WaiterQueueNode::Dequeue(WaiterQueueNode** head) { return DequeueMatching(head, [](WaiterQueueNode* node) { return true; }); } // static WaiterQueueNode* WaiterQueueNode::Split(WaiterQueueNode** head, uint32_t count) { DCHECK_GT(count, 0); DCHECK_NOT_NULL(head); DCHECK_NOT_NULL(*head); WaiterQueueNode* front_head = *head; WaiterQueueNode* back_head = front_head; uint32_t actual_count = 0; while (actual_count < count) { back_head = back_head->next_; // The queue is shorter than the requested count, return the whole queue. if (back_head == front_head) { *head = nullptr; return front_head; } actual_count++; } WaiterQueueNode* front_tail = back_head->prev_; WaiterQueueNode* back_tail = front_head->prev_; // Fix up the back list (i.e. remainder of the list). back_head->prev_ = back_tail; back_tail->next_ = back_head; *head = back_head; // Fix up and return the front list (i.e. the dequeued list). front_head->prev_ = front_tail; front_tail->next_ = front_head; return front_head; } // static int WaiterQueueNode::LengthFromHead(WaiterQueueNode* head) { WaiterQueueNode* cur = head; int len = 0; do { len++; cur = cur->next_; } while (cur != head); return len; } void WaiterQueueNode::Wait() { AllowGarbageCollection allow_before_parking; requester_->main_thread_local_heap()->ExecuteWhileParked([this]() { base::MutexGuard guard(&wait_lock_); while (should_wait_) { wait_cond_var_.Wait(&wait_lock_); } }); } // Returns false if timed out, true otherwise. bool WaiterQueueNode::WaitFor(const base::TimeDelta& rel_time) { bool result; AllowGarbageCollection allow_before_parking; requester_->main_thread_local_heap()->ExecuteWhileParked([this, rel_time, &result]() { base::MutexGuard guard(&wait_lock_); base::TimeTicks current_time = base::TimeTicks::Now(); base::TimeTicks timeout_time = current_time + rel_time; for (;;) { if (!should_wait_) { result = true; return; } current_time = base::TimeTicks::Now(); if (current_time >= timeout_time) { result = false; return; } base::TimeDelta time_until_timeout = timeout_time - current_time; bool wait_res = wait_cond_var_.WaitFor(&wait_lock_, time_until_timeout); USE(wait_res); // The wake up may have been spurious, so loop again. } }); return result; } void WaiterQueueNode::Notify() { base::MutexGuard guard(&wait_lock_); should_wait_ = false; wait_cond_var_.NotifyOne(); SetNotInListForVerification(); } uint32_t WaiterQueueNode::NotifyAllInList() { WaiterQueueNode* cur = this; uint32_t count = 0; do { WaiterQueueNode* next = cur->next_; cur->Notify(); cur = next; count++; } while (cur != this); return count; } void WaiterQueueNode::SbxCheckNotInList() const { SBXCHECK_EQ(nullptr, next_); SBXCHECK_EQ(nullptr, prev_); } void WaiterQueueNode::SetNotInListForVerification() { next_ = prev_ = nullptr; } } // namespace detail } // namespace internal } // namespace v8