OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium 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 #include "net/base/priority_dispatch.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 |
| 9 namespace net { |
| 10 |
| 11 // We rely on the priority enum values being sequential having starting at 0, |
| 12 // and increasing for lower priorities. |
| 13 COMPILE_ASSERT(HIGHEST == 0u && |
| 14 LOWEST > HIGHEST && |
| 15 IDLE > LOWEST && |
| 16 NUM_PRIORITIES > IDLE, |
| 17 priority_indexes_incompatible); |
| 18 |
| 19 // static |
| 20 PriorityDispatch::Limits PriorityDispatch::Limits::MakeAny( |
| 21 size_t max_idle) { |
| 22 Limits limits = {{0, 0, 0, 0, max_idle}}; |
| 23 return limits; |
| 24 } |
| 25 |
| 26 size_t PriorityDispatch::Limits::Total() const { |
| 27 size_t total = 0; |
| 28 for (size_t i = 0; i < NUM_PRIORITIES; ++i) { |
| 29 total+= reserved_slots[i]; |
| 30 } |
| 31 return total; |
| 32 } |
| 33 |
| 34 PriorityDispatch::PriorityDispatch(const Limits& limits, size_t max_queued) |
| 35 : num_running_jobs_(0), max_queued_jobs_(max_queued) { |
| 36 size_t total = 0; |
| 37 for (size_t i = 0; i < NUM_PRIORITIES; ++i) { |
| 38 total+= limits.reserved_slots[NUM_PRIORITIES - i - 1]; |
| 39 max_running_jobs_[NUM_PRIORITIES - i - 1] = total; |
| 40 } |
| 41 } |
| 42 |
| 43 PriorityDispatch::~PriorityDispatch() {} |
| 44 |
| 45 void PriorityDispatch::SetMaxQueued(size_t max_queued) { |
| 46 DCHECK_EQ(0u, num_queued_jobs()); |
| 47 max_queued_jobs_ = max_queued; |
| 48 } |
| 49 |
| 50 PriorityDispatch::Handle PriorityDispatch::Add(Job* job, |
| 51 RequestPriority priority) { |
| 52 DCHECK(job); |
| 53 if (num_running_jobs_ < max_running_jobs_[priority]) { |
| 54 ++num_running_jobs_; |
| 55 job->Start(); |
| 56 return Handle(); |
| 57 } |
| 58 Handle handle = queue_.Insert(job, priority); |
| 59 if (queue_.size() > max_queued_jobs_) { |
| 60 // Evict oldest lowest-priority job. |
| 61 Handle evicted = queue_.OldestLowest(); |
| 62 DCHECK(!evicted.is_null()); |
| 63 if (evicted.equals(handle)) |
| 64 handle = Handle(); |
| 65 Job* evicted_job = evicted.value(); |
| 66 queue_.Erase(evicted); |
| 67 DCHECK(evicted_job); |
| 68 evicted_job->OnEvicted(); |
| 69 } |
| 70 return handle; |
| 71 } |
| 72 |
| 73 void PriorityDispatch::Cancel(const Handle& handle) { |
| 74 queue_.Erase(handle); |
| 75 } |
| 76 |
| 77 PriorityDispatch::Handle PriorityDispatch::Update(const Handle& handle, |
| 78 RequestPriority priority) { |
| 79 DCHECK(!handle.is_null()); |
| 80 DCHECK_GE(num_running_jobs_, max_running_jobs_[handle.priority()]) << |
| 81 "Job should not be in queue when limits permit it to start."; |
| 82 if (num_running_jobs_ < max_running_jobs_[priority]) { |
| 83 Job* job = handle.value(); |
| 84 queue_.Erase(handle); |
| 85 ++num_running_jobs_; |
| 86 DCHECK(job); |
| 87 job->Start(); |
| 88 return Handle(); |
| 89 } |
| 90 return queue_.Move(handle, priority); |
| 91 } |
| 92 |
| 93 void PriorityDispatch::OnJobFinished() { |
| 94 DCHECK_GT(num_running_jobs_, 0u); |
| 95 --num_running_jobs_; |
| 96 Handle handle = queue_.First(); |
| 97 if (handle.is_null()) { |
| 98 DCHECK_EQ(0u, queue_.size()); |
| 99 return; |
| 100 } |
| 101 if (num_running_jobs_ < max_running_jobs_[handle.priority()]) { |
| 102 Job* job = handle.value(); |
| 103 queue_.Erase(handle); |
| 104 ++num_running_jobs_; |
| 105 DCHECK(job); |
| 106 job->Start(); |
| 107 } |
| 108 } |
| 109 |
| 110 } // namespace net |
| 111 |
| 112 |
OLD | NEW |