Index: net/base/network_throttle_manager_impl.cc |
diff --git a/net/base/network_throttle_manager_impl.cc b/net/base/network_throttle_manager_impl.cc |
deleted file mode 100644 |
index eda6fea2cfccc7c0f967d1aac4497e5ccd188252..0000000000000000000000000000000000000000 |
--- a/net/base/network_throttle_manager_impl.cc |
+++ /dev/null |
@@ -1,326 +0,0 @@ |
-// Copyright 2016 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 "net/base/network_throttle_manager_impl.h" |
- |
-#include <algorithm> |
- |
-#include "base/logging.h" |
-#include "base/threading/thread_task_runner_handle.h" |
-#include "base/time/default_tick_clock.h" |
- |
-namespace net { |
- |
-const size_t NetworkThrottleManagerImpl::kActiveRequestThrottlingLimit = 2; |
-const int NetworkThrottleManagerImpl::kMedianLifetimeMultiple = 5; |
- |
-// Initial estimate based on the median in the |
-// Net.RequestTime2.Success histogram, excluding cached results by eye. |
-const int NetworkThrottleManagerImpl::kInitialMedianInMs = 400; |
- |
-// Set timers slightly further into the future than they need to be set, so |
-// that the algorithm isn't vulnerable to timer round off errors triggering |
-// the callback before the throttle would be considered aged out of the set. |
-// Set to 17 to hanlde systems with |!base::TimeTicks::IsHighResolution()|. |
-// Note that even if the timer goes off before it should, all that should cost |
-// is a second task; this class does not rely on timer accuracy for its |
-// correctness. |
-const int kTimerFudgeInMs = 17; |
- |
-class NetworkThrottleManagerImpl::ThrottleImpl |
- : public NetworkThrottleManager::Throttle { |
- public: |
- // Allowed state transitions are BLOCKED -> OUTSTANDING -> AGED. |
- // Throttles may be created in the BLOCKED or OUTSTANDING states. |
- enum class State { |
- // Not allowed to proceed by manager. |
- BLOCKED, |
- |
- // Allowed to proceed, counts as an "outstanding" request for |
- // manager accounting purposes. |
- OUTSTANDING, |
- |
- // Old enough to not count as "outstanding" anymore for |
- // manager accounting purposes. |
- AGED |
- }; |
- |
- using ThrottleListQueuePointer = |
- NetworkThrottleManagerImpl::ThrottleList::iterator; |
- |
- // Caller must arrange that |*delegate| and |*manager| outlive |
- // the ThrottleImpl class. |
- ThrottleImpl(bool blocked, |
- RequestPriority priority, |
- ThrottleDelegate* delegate, |
- NetworkThrottleManagerImpl* manager, |
- ThrottleListQueuePointer queue_pointer); |
- |
- ~ThrottleImpl() override; |
- |
- // Throttle: |
- bool IsBlocked() const override; |
- RequestPriority Priority() const override; |
- void SetPriority(RequestPriority priority) override; |
- |
- State state() const { return state_; } |
- |
- ThrottleListQueuePointer queue_pointer() const { return queue_pointer_; } |
- void set_queue_pointer(const ThrottleListQueuePointer& pointer) { |
- if (state_ != State::AGED) |
- DCHECK_EQ(this, *pointer); |
- queue_pointer_ = pointer; |
- } |
- |
- void set_start_time(base::TimeTicks start_time) { start_time_ = start_time; } |
- base::TimeTicks start_time() const { return start_time_; } |
- |
- // Change the throttle's state to AGED. The previous |
- // state must be OUTSTANDING. |
- void SetAged(); |
- |
- // Note that this call calls the delegate, and hence may result in |
- // re-entrant calls into the manager or ThrottleImpl. The manager should |
- // not rely on any state other than its own existence being persistent |
- // across this call. |
- void NotifyUnblocked(); |
- |
- private: |
- State state_; |
- RequestPriority priority_; |
- ThrottleDelegate* const delegate_; |
- NetworkThrottleManagerImpl* const manager_; |
- |
- base::TimeTicks start_time_; |
- |
- // To allow deletion from the blocked queue (when the throttle is in the |
- // blocked queue). |
- ThrottleListQueuePointer queue_pointer_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ThrottleImpl); |
-}; |
- |
-NetworkThrottleManagerImpl::ThrottleImpl::ThrottleImpl( |
- bool blocked, |
- RequestPriority priority, |
- NetworkThrottleManager::ThrottleDelegate* delegate, |
- NetworkThrottleManagerImpl* manager, |
- ThrottleListQueuePointer queue_pointer) |
- : state_(blocked ? State::BLOCKED : State::OUTSTANDING), |
- priority_(priority), |
- delegate_(delegate), |
- manager_(manager), |
- queue_pointer_(queue_pointer) { |
- DCHECK(delegate); |
- if (!blocked) |
- start_time_ = manager->tick_clock_->NowTicks(); |
-} |
- |
-NetworkThrottleManagerImpl::ThrottleImpl::~ThrottleImpl() { |
- manager_->OnThrottleDestroyed(this); |
-} |
- |
-bool NetworkThrottleManagerImpl::ThrottleImpl::IsBlocked() const { |
- return state_ == State::BLOCKED; |
-} |
- |
-RequestPriority NetworkThrottleManagerImpl::ThrottleImpl::Priority() const { |
- return priority_; |
-} |
- |
-void NetworkThrottleManagerImpl::ThrottleImpl::SetPriority( |
- RequestPriority new_priority) { |
- RequestPriority old_priority(priority_); |
- if (old_priority == new_priority) |
- return; |
- priority_ = new_priority; |
- manager_->OnThrottlePriorityChanged(this, old_priority, new_priority); |
-} |
- |
-void NetworkThrottleManagerImpl::ThrottleImpl::SetAged() { |
- DCHECK_EQ(State::OUTSTANDING, state_); |
- state_ = State::AGED; |
-} |
- |
-void NetworkThrottleManagerImpl::ThrottleImpl::NotifyUnblocked() { |
- // This method should only be called once, and only if the |
- // current state is blocked. |
- DCHECK_EQ(State::BLOCKED, state_); |
- state_ = State::OUTSTANDING; |
- delegate_->OnThrottleUnblocked(this); |
-} |
- |
-NetworkThrottleManagerImpl::NetworkThrottleManagerImpl() |
- : lifetime_median_estimate_(PercentileEstimator::kMedianPercentile, |
- kInitialMedianInMs), |
- outstanding_recomputation_timer_(false /* retain_user_task */, |
- false /* is_repeating */), |
- tick_clock_(new base::DefaultTickClock()), |
- weak_ptr_factory_(this) { |
- outstanding_recomputation_timer_.SetTaskRunner( |
- base::ThreadTaskRunnerHandle::Get()); |
-} |
- |
-NetworkThrottleManagerImpl::~NetworkThrottleManagerImpl() {} |
- |
-std::unique_ptr<NetworkThrottleManager::Throttle> |
-NetworkThrottleManagerImpl::CreateThrottle( |
- NetworkThrottleManager::ThrottleDelegate* delegate, |
- RequestPriority priority, |
- bool ignore_limits) { |
- bool blocked = |
- (!ignore_limits && priority == THROTTLED && |
- outstanding_throttles_.size() >= kActiveRequestThrottlingLimit); |
- |
- std::unique_ptr<NetworkThrottleManagerImpl::ThrottleImpl> throttle( |
- new ThrottleImpl(blocked, priority, delegate, this, |
- blocked_throttles_.end())); |
- |
- ThrottleList& insert_list(blocked ? blocked_throttles_ |
- : outstanding_throttles_); |
- |
- throttle->set_queue_pointer( |
- insert_list.insert(insert_list.end(), throttle.get())); |
- |
- // In case oustanding_throttles_ was empty, set up timer. |
- if (!blocked) |
- RecomputeOutstanding(); |
- |
- return std::move(throttle); |
-} |
- |
-void NetworkThrottleManagerImpl::SetTickClockForTesting( |
- std::unique_ptr<base::TickClock> tick_clock) { |
- tick_clock_ = std::move(tick_clock); |
-} |
- |
-bool NetworkThrottleManagerImpl::ConditionallyTriggerTimerForTesting() { |
- if (!outstanding_recomputation_timer_.IsRunning() || |
- (tick_clock_->NowTicks() < |
- outstanding_recomputation_timer_.desired_run_time())) { |
- return false; |
- } |
- |
- base::Closure timer_callback(outstanding_recomputation_timer_.user_task()); |
- outstanding_recomputation_timer_.Stop(); |
- timer_callback.Run(); |
- return true; |
-} |
- |
-void NetworkThrottleManagerImpl::OnThrottlePriorityChanged( |
- NetworkThrottleManagerImpl::ThrottleImpl* throttle, |
- RequestPriority old_priority, |
- RequestPriority new_priority) { |
- // The only case requiring a state change is if the priority change |
- // implies unblocking, which can only happen on a transition from blocked |
- // (implies THROTTLED) to non-THROTTLED. |
- if (throttle->IsBlocked() && new_priority != THROTTLED) { |
- // May result in re-entrant calls into this class. |
- UnblockThrottle(throttle); |
- } |
-} |
- |
-void NetworkThrottleManagerImpl::OnThrottleDestroyed(ThrottleImpl* throttle) { |
- switch (throttle->state()) { |
- case ThrottleImpl::State::BLOCKED: |
- DCHECK(throttle->queue_pointer() != blocked_throttles_.end()); |
- DCHECK_EQ(throttle, *(throttle->queue_pointer())); |
- blocked_throttles_.erase(throttle->queue_pointer()); |
- break; |
- case ThrottleImpl::State::OUTSTANDING: |
- DCHECK(throttle->queue_pointer() != outstanding_throttles_.end()); |
- DCHECK_EQ(throttle, *(throttle->queue_pointer())); |
- outstanding_throttles_.erase(throttle->queue_pointer()); |
- // Fall through |
- case ThrottleImpl::State::AGED: |
- DCHECK(!throttle->start_time().is_null()); |
- lifetime_median_estimate_.AddSample( |
- (tick_clock_->NowTicks() - throttle->start_time()) |
- .InMillisecondsRoundedUp()); |
- break; |
- } |
- |
- DCHECK(std::find(blocked_throttles_.begin(), blocked_throttles_.end(), |
- throttle) == blocked_throttles_.end()); |
- DCHECK(std::find(outstanding_throttles_.begin(), outstanding_throttles_.end(), |
- throttle) == outstanding_throttles_.end()); |
- |
- // Unblock the throttles if there's some chance there's a throttle to |
- // unblock. |
- if (outstanding_throttles_.size() < kActiveRequestThrottlingLimit && |
- !blocked_throttles_.empty()) { |
- // Via PostTask so there aren't upcalls from within destructors. |
- base::ThreadTaskRunnerHandle::Get()->PostTask( |
- FROM_HERE, |
- base::Bind(&NetworkThrottleManagerImpl::MaybeUnblockThrottles, |
- weak_ptr_factory_.GetWeakPtr())); |
- } |
-} |
- |
-void NetworkThrottleManagerImpl::RecomputeOutstanding() { |
- // Remove all throttles that have aged out of the outstanding set. |
- base::TimeTicks now(tick_clock_->NowTicks()); |
- base::TimeDelta age_horizon(base::TimeDelta::FromMilliseconds(( |
- kMedianLifetimeMultiple * lifetime_median_estimate_.current_estimate()))); |
- while (!outstanding_throttles_.empty()) { |
- ThrottleImpl* throttle = *outstanding_throttles_.begin(); |
- if (throttle->start_time() + age_horizon >= now) |
- break; |
- |
- outstanding_throttles_.erase(outstanding_throttles_.begin()); |
- throttle->SetAged(); |
- throttle->set_queue_pointer(outstanding_throttles_.end()); |
- } |
- |
- if (outstanding_throttles_.empty()) |
- return; |
- |
- // If the timer is already running, be conservative and leave it alone; |
- // the time for which it would be set will only be later than when it's |
- // currently set. |
- // This addresses, e.g., situations where a RecomputeOutstanding() races |
- // with a running timer which would unblock blocked throttles. |
- if (outstanding_recomputation_timer_.IsRunning()) |
- return; |
- |
- ThrottleImpl* first_throttle(*outstanding_throttles_.begin()); |
- DCHECK_GE(first_throttle->start_time() + age_horizon, now); |
- outstanding_recomputation_timer_.Start( |
- FROM_HERE, ((first_throttle->start_time() + age_horizon) - now + |
- base::TimeDelta::FromMilliseconds(kTimerFudgeInMs)), |
- // Unretained use of |this| is safe because the timer is |
- // owned by this object, and will be torn down if this object |
- // is destroyed. |
- base::Bind(&NetworkThrottleManagerImpl::MaybeUnblockThrottles, |
- base::Unretained(this))); |
-} |
- |
-void NetworkThrottleManagerImpl::UnblockThrottle(ThrottleImpl* throttle) { |
- DCHECK(throttle->IsBlocked()); |
- |
- blocked_throttles_.erase(throttle->queue_pointer()); |
- throttle->set_start_time(tick_clock_->NowTicks()); |
- throttle->set_queue_pointer( |
- outstanding_throttles_.insert(outstanding_throttles_.end(), throttle)); |
- |
- // Called in case |*throttle| was added to a null set. |
- RecomputeOutstanding(); |
- |
- // May result in re-entrant calls into this class. |
- throttle->NotifyUnblocked(); |
-} |
- |
-void NetworkThrottleManagerImpl::MaybeUnblockThrottles() { |
- RecomputeOutstanding(); |
- |
- while (outstanding_throttles_.size() < kActiveRequestThrottlingLimit && |
- !blocked_throttles_.empty()) { |
- // NOTE: This call may result in reentrant calls into |
- // NetworkThrottleManagerImpl; no state should be assumed to be |
- // persistent across this call. |
- UnblockThrottle(blocked_throttles_.front()); |
- } |
-} |
- |
-} // namespace net |