blob: e416ed068e9545d6ec37c13fd86626b5a76dd5bc [file] [log] [blame]
// 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.h"
#include "base/logging.h"
#include "net/base/priority_queue.h"
namespace net {
namespace {
class NetworkThrottleManagerImpl : public NetworkThrottleManager {
public:
class ThrottleImpl : public NetworkThrottleManager::Throttle {
public:
using QueuePointer = PriorityQueue<ThrottleImpl*>::Pointer;
// Caller must arrange that |*delegate| and |*throttler| outlive
// the ThrottleImpl class.
ThrottleImpl(bool throttled,
RequestPriority priority,
ThrottleDelegate* delegate,
NetworkThrottleManagerImpl* throttler);
~ThrottleImpl() override;
// Throttle
bool IsThrottled() const override;
void SetPriority(RequestPriority priority) override;
QueuePointer queue_pointer() const { return queue_pointer_; }
void set_queue_pointer(const QueuePointer& pointer) {
queue_pointer_ = pointer;
}
// Note that this call calls the delegate, and hence
// may result in re-entrant calls into the throttler or
// ThrottleImpl. The throttler should not rely on
// any state other than its own existence being persistent
// across this call.
void NotifyUnthrottled();
private:
bool throttled_;
ThrottleDelegate* const delegate_;
PriorityQueue<ThrottleImpl*>::Pointer queue_pointer_;
NetworkThrottleManagerImpl* const throttler_;
DISALLOW_COPY_AND_ASSIGN(ThrottleImpl);
};
NetworkThrottleManagerImpl();
~NetworkThrottleManagerImpl() override;
std::unique_ptr<Throttle> CreateThrottle(ThrottleDelegate* delegate,
RequestPriority priority,
bool ignore_limits) override;
private:
void OnStreamPriorityChanged(ThrottleImpl* throttle,
RequestPriority new_priority);
void OnStreamDestroyed(ThrottleImpl* throttle);
PriorityQueue<ThrottleImpl*> priority_queue_;
DISALLOW_COPY_AND_ASSIGN(NetworkThrottleManagerImpl);
};
// Currently this is a null implementation that does no throttling;
// all entries are created in the unthrottled state, and no throttle state
// change notifications are transmitted.
NetworkThrottleManagerImpl::ThrottleImpl::ThrottleImpl(
bool throttled,
RequestPriority priority,
NetworkThrottleManager::ThrottleDelegate* delegate,
NetworkThrottleManagerImpl* throttler)
: throttled_(throttled), delegate_(delegate), throttler_(throttler) {
DCHECK(delegate);
}
NetworkThrottleManagerImpl::ThrottleImpl::~ThrottleImpl() {
throttler_->OnStreamDestroyed(this);
}
void NetworkThrottleManagerImpl::ThrottleImpl::SetPriority(
RequestPriority priority) {
throttler_->OnStreamPriorityChanged(this, priority);
}
bool NetworkThrottleManagerImpl::ThrottleImpl::IsThrottled() const {
return throttled_;
}
void NetworkThrottleManagerImpl::ThrottleImpl::NotifyUnthrottled() {
// This methods should only be called once, and only if the
// current state is throttled.
DCHECK(throttled_);
throttled_ = false;
delegate_->OnThrottleStateChanged();
}
NetworkThrottleManagerImpl::NetworkThrottleManagerImpl()
: priority_queue_(MAXIMUM_PRIORITY + 1) {}
NetworkThrottleManagerImpl::~NetworkThrottleManagerImpl() {}
std::unique_ptr<NetworkThrottleManager::Throttle>
NetworkThrottleManagerImpl::CreateThrottle(
NetworkThrottleManager::ThrottleDelegate* delegate,
RequestPriority priority,
bool ignore_limits) {
std::unique_ptr<NetworkThrottleManagerImpl::ThrottleImpl> stream(
new ThrottleImpl(false, priority, delegate, this));
stream->set_queue_pointer(priority_queue_.Insert(stream.get(), priority));
return std::move(stream);
}
void NetworkThrottleManagerImpl::OnStreamPriorityChanged(
NetworkThrottleManagerImpl::ThrottleImpl* stream,
RequestPriority new_priority) {
priority_queue_.Erase(stream->queue_pointer());
stream->set_queue_pointer(priority_queue_.Insert(stream, new_priority));
}
void NetworkThrottleManagerImpl::OnStreamDestroyed(ThrottleImpl* stream) {
priority_queue_.Erase(stream->queue_pointer());
}
} // namespace
// static
std::unique_ptr<NetworkThrottleManager>
NetworkThrottleManager::CreateThrottler() {
return std::unique_ptr<NetworkThrottleManager>(
new NetworkThrottleManagerImpl);
}
} // namespace net