1 // Copyright (c) 2012 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.
5 #include "net/base/prioritized_dispatcher.h"
7 #include "base/logging.h"
11 PrioritizedDispatcher::Limits::Limits(Priority num_priorities
,
13 : total_jobs(total_jobs
), reserved_slots(num_priorities
) {}
15 PrioritizedDispatcher::Limits::~Limits() {}
17 PrioritizedDispatcher::PrioritizedDispatcher(const Limits
& limits
)
18 : queue_(limits
.reserved_slots
.size()),
19 max_running_jobs_(limits
.reserved_slots
.size()),
20 num_running_jobs_(0) {
22 for (size_t i
= 0; i
< limits
.reserved_slots
.size(); ++i
) {
23 total
+= limits
.reserved_slots
[i
];
24 max_running_jobs_
[i
] = total
;
26 // Unreserved slots are available for all priorities.
27 DCHECK_LE(total
, limits
.total_jobs
) << "sum(reserved_slots) <= total_jobs";
28 size_t spare
= limits
.total_jobs
- total
;
29 for (size_t i
= limits
.reserved_slots
.size(); i
> 0; --i
) {
30 max_running_jobs_
[i
- 1] += spare
;
34 PrioritizedDispatcher::~PrioritizedDispatcher() {}
36 PrioritizedDispatcher::Handle
PrioritizedDispatcher::Add(
37 Job
* job
, Priority priority
) {
39 DCHECK_LT(priority
, num_priorities());
40 if (num_running_jobs_
< max_running_jobs_
[priority
]) {
45 return queue_
.Insert(job
, priority
);
48 void PrioritizedDispatcher::Cancel(const Handle
& handle
) {
52 PrioritizedDispatcher::Job
* PrioritizedDispatcher::EvictOldestLowest() {
53 Handle handle
= queue_
.FirstMin();
56 Job
* job
= handle
.value();
61 PrioritizedDispatcher::Handle
PrioritizedDispatcher::ChangePriority(
62 const Handle
& handle
, Priority priority
) {
63 DCHECK(!handle
.is_null());
64 DCHECK_LT(priority
, num_priorities());
65 DCHECK_GE(num_running_jobs_
, max_running_jobs_
[handle
.priority()]) <<
66 "Job should not be in queue when limits permit it to start.";
68 if (handle
.priority() == priority
)
71 if (MaybeDispatchJob(handle
, priority
))
73 Job
* job
= handle
.value();
75 return queue_
.Insert(job
, priority
);
78 void PrioritizedDispatcher::OnJobFinished() {
79 DCHECK_GT(num_running_jobs_
, 0u);
81 Handle handle
= queue_
.FirstMax();
82 if (handle
.is_null()) {
83 DCHECK_EQ(0u, queue_
.size());
86 MaybeDispatchJob(handle
, handle
.priority());
89 bool PrioritizedDispatcher::MaybeDispatchJob(const Handle
& handle
,
90 Priority job_priority
) {
91 DCHECK_LT(job_priority
, num_priorities());
92 if (num_running_jobs_
>= max_running_jobs_
[job_priority
])
94 Job
* job
= handle
.value();