Index: net/base/network_stream_throttler.cc |
diff --git a/net/base/network_stream_throttler.cc b/net/base/network_stream_throttler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c3248ddde47974fd0a920d1dad209280fbd8032e |
--- /dev/null |
+++ b/net/base/network_stream_throttler.cc |
@@ -0,0 +1,138 @@ |
+// 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_stream_throttler.h" |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+class NetworkStreamThrottlerImpl : public NetworkStreamThrottler { |
+ public: |
+ class ThrottleImpl : public NetworkStreamThrottler::Throttle { |
+ public: |
+ ~ThrottleImpl() override; |
+ |
+ // Throttle |
+ bool IsThrottled() const override { return throttled_; } |
+ void SetPriority(RequestPriority priority) override; |
+ |
+ private: |
+ friend NetworkStreamThrottlerImpl; |
+ |
+ using QueuePointer = PriorityQueue<ThrottleImpl*>::Pointer; |
+ |
+ // Caller must arrange that |*delegate| and |*throttler| outlives |
+ // the ThrottleImpl class. |
+ ThrottleImpl(bool throttled, |
+ RequestPriority priority, |
+ Delegate* delegate, |
+ NetworkStreamThrottlerImpl* throttler); |
+ |
+ 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 throtter or |
+ // ThrottleImpl. The throttler should not rely on |
+ // any state other than its own existence being persistent |
+ // across this call. |
+ void NotifyUnthrottled(); |
+ |
+ bool throttled_; |
+ Delegate* const delegate_; |
+ PriorityQueue<ThrottleImpl*>::Pointer queue_pointer_; |
+ |
+ NetworkStreamThrottlerImpl* const throttler_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ThrottleImpl); |
+ }; |
+ |
+ NetworkStreamThrottlerImpl(); |
+ ~NetworkStreamThrottlerImpl() override; |
+ |
+ std::unique_ptr<Throttle> CreateThrottle(Delegate* 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(NetworkStreamThrottlerImpl); |
+}; |
+ |
+// 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. |
+ |
+NetworkStreamThrottlerImpl::ThrottleImpl::~ThrottleImpl() { |
+ if (throttler_) |
+ throttler_->OnStreamDestroyed(this); |
+} |
+ |
+void NetworkStreamThrottlerImpl::ThrottleImpl::SetPriority( |
+ RequestPriority priority) { |
+ if (throttler_) |
+ throttler_->OnStreamPriorityChanged(this, priority); |
+} |
+ |
+NetworkStreamThrottlerImpl::ThrottleImpl::ThrottleImpl( |
+ bool throttled, |
+ RequestPriority priority, |
+ NetworkStreamThrottler::Delegate* delegate, |
+ NetworkStreamThrottlerImpl* throttler) |
+ : throttled_(throttled), delegate_(delegate), throttler_(throttler) {} |
+ |
+void NetworkStreamThrottlerImpl::ThrottleImpl::NotifyUnthrottled() { |
+ throttled_ = false; |
+ // TODO(rdsmith): Figure out if/how this needs to be made asynchronous. |
+ if (delegate_) |
+ delegate_->OnThrottleStateChanged(); |
+} |
+ |
+NetworkStreamThrottlerImpl::NetworkStreamThrottlerImpl() |
+ : priority_queue_(MAXIMUM_PRIORITY + 1) {} |
+ |
+NetworkStreamThrottlerImpl::~NetworkStreamThrottlerImpl() {} |
+ |
+std::unique_ptr<NetworkStreamThrottler::Throttle> |
+NetworkStreamThrottlerImpl::CreateThrottle( |
+ NetworkStreamThrottler::Delegate* delegate, |
+ RequestPriority priority, |
+ bool ignore_limits) { |
+ std::unique_ptr<NetworkStreamThrottlerImpl::ThrottleImpl> stream( |
+ new ThrottleImpl(false, priority, delegate, this)); |
+ |
+ stream->set_queue_pointer(priority_queue_.Insert(stream.get(), priority)); |
+ |
+ return std::move(stream); |
+} |
+ |
+void NetworkStreamThrottlerImpl::OnStreamPriorityChanged( |
+ NetworkStreamThrottlerImpl::ThrottleImpl* stream, |
+ RequestPriority new_priority) { |
+ priority_queue_.Erase(stream->queue_pointer()); |
+ stream->set_queue_pointer(priority_queue_.Insert(stream, new_priority)); |
+} |
+ |
+void NetworkStreamThrottlerImpl::OnStreamDestroyed(ThrottleImpl* stream) { |
+ priority_queue_.Erase(stream->queue_pointer()); |
+} |
+ |
+} // namespace |
+ |
+// static |
+std::unique_ptr<NetworkStreamThrottler> |
+NetworkStreamThrottler::CreateThrottler() { |
+ return std::unique_ptr<NetworkStreamThrottler>( |
+ new NetworkStreamThrottlerImpl); |
+} |
+ |
+} // namespace net |