mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 16:26:10 +03:00
173 lines
6.2 KiB
C++
173 lines
6.2 KiB
C++
|
// Copyright 2015 The Chromium 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 "base/task/sequence_manager/work_queue_sets.h"
|
||
|
|
||
|
#include "base/logging.h"
|
||
|
|
||
|
namespace base {
|
||
|
namespace sequence_manager {
|
||
|
namespace internal {
|
||
|
|
||
|
WorkQueueSets::WorkQueueSets(size_t num_sets, const char* name)
|
||
|
: work_queue_heaps_(num_sets), name_(name) {}
|
||
|
|
||
|
WorkQueueSets::~WorkQueueSets() = default;
|
||
|
|
||
|
void WorkQueueSets::AddQueue(WorkQueue* work_queue, size_t set_index) {
|
||
|
DCHECK(!work_queue->work_queue_sets());
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
EnqueueOrder enqueue_order;
|
||
|
bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
|
||
|
work_queue->AssignToWorkQueueSets(this);
|
||
|
work_queue->AssignSetIndex(set_index);
|
||
|
if (!has_enqueue_order)
|
||
|
return;
|
||
|
work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::RemoveQueue(WorkQueue* work_queue) {
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
work_queue->AssignToWorkQueueSets(nullptr);
|
||
|
HeapHandle heap_handle = work_queue->heap_handle();
|
||
|
if (!heap_handle.IsValid())
|
||
|
return;
|
||
|
size_t set_index = work_queue->work_queue_set_index();
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
work_queue_heaps_[set_index].erase(heap_handle);
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::ChangeSetIndex(WorkQueue* work_queue, size_t set_index) {
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
EnqueueOrder enqueue_order;
|
||
|
bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
|
||
|
size_t old_set = work_queue->work_queue_set_index();
|
||
|
DCHECK_LT(old_set, work_queue_heaps_.size());
|
||
|
DCHECK_NE(old_set, set_index);
|
||
|
work_queue->AssignSetIndex(set_index);
|
||
|
if (!has_enqueue_order)
|
||
|
return;
|
||
|
work_queue_heaps_[old_set].erase(work_queue->heap_handle());
|
||
|
work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::OnFrontTaskChanged(WorkQueue* work_queue) {
|
||
|
EnqueueOrder enqueue_order;
|
||
|
bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
|
||
|
DCHECK(has_enqueue_order);
|
||
|
size_t set = work_queue->work_queue_set_index();
|
||
|
work_queue_heaps_[set].ChangeKey(work_queue->heap_handle(),
|
||
|
{enqueue_order, work_queue});
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::OnTaskPushedToEmptyQueue(WorkQueue* work_queue) {
|
||
|
// NOTE if this function changes, we need to keep |WorkQueueSets::AddQueue| in
|
||
|
// sync.
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
EnqueueOrder enqueue_order;
|
||
|
bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
|
||
|
DCHECK(has_enqueue_order);
|
||
|
size_t set_index = work_queue->work_queue_set_index();
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size())
|
||
|
<< " set_index = " << set_index;
|
||
|
// |work_queue| should not be in work_queue_heaps_[set_index].
|
||
|
DCHECK(!work_queue->heap_handle().IsValid());
|
||
|
work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::OnPopQueue(WorkQueue* work_queue) {
|
||
|
// Assume that |work_queue| contains the lowest enqueue_order.
|
||
|
size_t set_index = work_queue->work_queue_set_index();
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
DCHECK(!work_queue_heaps_[set_index].empty()) << " set_index = " << set_index;
|
||
|
DCHECK_EQ(work_queue_heaps_[set_index].Min().value, work_queue)
|
||
|
<< " set_index = " << set_index;
|
||
|
DCHECK(work_queue->heap_handle().IsValid());
|
||
|
EnqueueOrder enqueue_order;
|
||
|
if (work_queue->GetFrontTaskEnqueueOrder(&enqueue_order)) {
|
||
|
// O(log n)
|
||
|
work_queue_heaps_[set_index].ReplaceMin({enqueue_order, work_queue});
|
||
|
} else {
|
||
|
// O(log n)
|
||
|
work_queue_heaps_[set_index].Pop();
|
||
|
DCHECK(work_queue_heaps_[set_index].empty() ||
|
||
|
work_queue_heaps_[set_index].Min().value != work_queue);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WorkQueueSets::OnQueueBlocked(WorkQueue* work_queue) {
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
HeapHandle heap_handle = work_queue->heap_handle();
|
||
|
if (!heap_handle.IsValid())
|
||
|
return;
|
||
|
size_t set_index = work_queue->work_queue_set_index();
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
work_queue_heaps_[set_index].erase(heap_handle);
|
||
|
}
|
||
|
|
||
|
bool WorkQueueSets::GetOldestQueueInSet(size_t set_index,
|
||
|
WorkQueue** out_work_queue) const {
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
if (work_queue_heaps_[set_index].empty())
|
||
|
return false;
|
||
|
*out_work_queue = work_queue_heaps_[set_index].Min().value;
|
||
|
DCHECK_EQ(set_index, (*out_work_queue)->work_queue_set_index());
|
||
|
DCHECK((*out_work_queue)->heap_handle().IsValid());
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WorkQueueSets::GetOldestQueueAndEnqueueOrderInSet(
|
||
|
size_t set_index,
|
||
|
WorkQueue** out_work_queue,
|
||
|
EnqueueOrder* out_enqueue_order) const {
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size());
|
||
|
if (work_queue_heaps_[set_index].empty())
|
||
|
return false;
|
||
|
const OldestTaskEnqueueOrder& oldest = work_queue_heaps_[set_index].Min();
|
||
|
*out_work_queue = oldest.value;
|
||
|
*out_enqueue_order = oldest.key;
|
||
|
EnqueueOrder enqueue_order;
|
||
|
DCHECK(oldest.value->GetFrontTaskEnqueueOrder(&enqueue_order) &&
|
||
|
oldest.key == enqueue_order);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WorkQueueSets::IsSetEmpty(size_t set_index) const {
|
||
|
DCHECK_LT(set_index, work_queue_heaps_.size())
|
||
|
<< " set_index = " << set_index;
|
||
|
return work_queue_heaps_[set_index].empty();
|
||
|
}
|
||
|
|
||
|
#if DCHECK_IS_ON() || !defined(NDEBUG)
|
||
|
bool WorkQueueSets::ContainsWorkQueueForTest(
|
||
|
const WorkQueue* work_queue) const {
|
||
|
EnqueueOrder enqueue_order;
|
||
|
bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
|
||
|
|
||
|
for (const IntrusiveHeap<OldestTaskEnqueueOrder>& heap : work_queue_heaps_) {
|
||
|
for (const OldestTaskEnqueueOrder& heap_value_pair : heap) {
|
||
|
if (heap_value_pair.value == work_queue) {
|
||
|
DCHECK(has_enqueue_order);
|
||
|
DCHECK_EQ(heap_value_pair.key, enqueue_order);
|
||
|
DCHECK_EQ(this, work_queue->work_queue_sets());
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (work_queue->work_queue_sets() == this) {
|
||
|
DCHECK(!has_enqueue_order);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
} // namespace internal
|
||
|
} // namespace sequence_manager
|
||
|
} // namespace base
|