Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(377)

Side by Side Diff: net/websockets/websocket_throttle.cc

Issue 18932005: Reduce the complexity of WebSocketThrottle's wakeup code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: android_dbg build fix Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/websockets/websocket_throttle.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/websockets/websocket_throttle.h" 5 #include "net/websockets/websocket_throttle.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <utility>
10 11
11 #include "base/memory/singleton.h" 12 #include "base/memory/singleton.h"
12 #include "base/message_loop.h" 13 #include "base/message_loop.h"
13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
16 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
17 #include "net/socket_stream/socket_stream.h" 18 #include "net/socket_stream/socket_stream.h"
18 #include "net/websockets/websocket_job.h" 19 #include "net/websockets/websocket_job.h"
19 20
20 namespace net { 21 namespace net {
21 22
23 namespace {
24
25 const size_t kMaxWebSocketJobsThrottled = 1024;
26
27 } // namespace
28
22 WebSocketThrottle::WebSocketThrottle() { 29 WebSocketThrottle::WebSocketThrottle() {
23 } 30 }
24 31
25 WebSocketThrottle::~WebSocketThrottle() { 32 WebSocketThrottle::~WebSocketThrottle() {
26 DCHECK(queue_.empty()); 33 DCHECK(queue_.empty());
27 DCHECK(addr_map_.empty()); 34 DCHECK(addr_map_.empty());
28 } 35 }
29 36
30 // static 37 // static
31 WebSocketThrottle* WebSocketThrottle::GetInstance() { 38 WebSocketThrottle* WebSocketThrottle::GetInstance() {
32 return Singleton<WebSocketThrottle>::get(); 39 return Singleton<WebSocketThrottle>::get();
33 } 40 }
34 41
35 void WebSocketThrottle::PutInQueue(WebSocketJob* job) { 42 bool WebSocketThrottle::PutInQueue(WebSocketJob* job) {
43 if (queue_.size() >= kMaxWebSocketJobsThrottled)
44 return false;
45
36 queue_.push_back(job); 46 queue_.push_back(job);
37 const AddressList& address_list = job->address_list(); 47 const AddressList& address_list = job->address_list();
38 std::set<IPEndPoint> address_set; 48 std::set<IPEndPoint> address_set;
39 for (AddressList::const_iterator addr_iter = address_list.begin(); 49 for (AddressList::const_iterator addr_iter = address_list.begin();
40 addr_iter != address_list.end(); 50 addr_iter != address_list.end();
41 ++addr_iter) { 51 ++addr_iter) {
42 const IPEndPoint& address = *addr_iter; 52 const IPEndPoint& address = *addr_iter;
43 // If |address| is already processed, don't do it again. 53 // If |address| is already processed, don't do it again.
44 if (!address_set.insert(address).second) 54 if (!address_set.insert(address).second)
45 continue; 55 continue;
46 56
47 ConnectingAddressMap::iterator iter = addr_map_.find(address); 57 ConnectingAddressMap::iterator iter = addr_map_.find(address);
48 if (iter == addr_map_.end()) { 58 if (iter == addr_map_.end()) {
49 ConnectingQueue* queue = new ConnectingQueue(); 59 ConnectingAddressMap::iterator new_queue =
50 queue->push_back(job); 60 addr_map_.insert(make_pair(address, ConnectingQueue())).first;
51 addr_map_[address] = queue; 61 new_queue->second.push_back(job);
52 } else { 62 } else {
53 iter->second->push_back(job); 63 DCHECK(!iter->second.empty());
64 iter->second.push_back(job);
54 job->SetWaiting(); 65 job->SetWaiting();
55 DVLOG(1) << "Waiting on " << address.ToString(); 66 DVLOG(1) << "Waiting on " << address.ToString();
56 } 67 }
57 } 68 }
69
70 return true;
58 } 71 }
59 72
60 void WebSocketThrottle::RemoveFromQueue(WebSocketJob* job) { 73 void WebSocketThrottle::RemoveFromQueue(WebSocketJob* job) {
61 ConnectingQueue::iterator queue_iter = 74 ConnectingQueue::iterator queue_iter =
62 std::find(queue_.begin(), queue_.end(), job); 75 std::find(queue_.begin(), queue_.end(), job);
63 if (queue_iter == queue_.end()) 76 if (queue_iter == queue_.end())
64 return; 77 return;
65 queue_.erase(queue_iter); 78 queue_.erase(queue_iter);
66 const AddressList& address_list = job->address_list(); 79
80 std::set<WebSocketJob*> wakeup_candidates;
81
82 const AddressList& resolved_address_list = job->address_list();
67 std::set<IPEndPoint> address_set; 83 std::set<IPEndPoint> address_set;
68 for (AddressList::const_iterator addr_iter = address_list.begin(); 84 for (AddressList::const_iterator addr_iter = resolved_address_list.begin();
69 addr_iter != address_list.end(); 85 addr_iter != resolved_address_list.end();
70 ++addr_iter) { 86 ++addr_iter) {
71 const IPEndPoint& address = *addr_iter; 87 const IPEndPoint& address = *addr_iter;
72 // If |address| is already processed, don't do it again. 88 // If |address| is already processed, don't do it again.
73 if (!address_set.insert(address).second) 89 if (!address_set.insert(address).second)
74 continue; 90 continue;
75 91
76 ConnectingAddressMap::iterator map_iter = addr_map_.find(address); 92 ConnectingAddressMap::iterator map_iter = addr_map_.find(address);
77 DCHECK(map_iter != addr_map_.end()); 93 DCHECK(map_iter != addr_map_.end());
78 94
79 ConnectingQueue* queue = map_iter->second; 95 ConnectingQueue& per_address_queue = map_iter->second;
80 // Job may not be front of queue if the socket is closed while waiting. 96 DCHECK(!per_address_queue.empty());
81 ConnectingQueue::iterator address_queue_iter = 97 // Job may not be front of the queue if the socket is closed while waiting.
82 std::find(queue->begin(), queue->end(), job); 98 ConnectingQueue::iterator per_address_queue_iter =
83 if (address_queue_iter != queue->end()) 99 std::find(per_address_queue.begin(), per_address_queue.end(), job);
84 queue->erase(address_queue_iter); 100 bool was_front = false;
85 if (queue->empty()) { 101 if (per_address_queue_iter != per_address_queue.end()) {
86 delete queue; 102 was_front = (per_address_queue_iter == per_address_queue.begin());
103 per_address_queue.erase(per_address_queue_iter);
104 }
105 if (per_address_queue.empty()) {
87 addr_map_.erase(map_iter); 106 addr_map_.erase(map_iter);
107 } else if (was_front) {
108 // The new front is a wake-up candidate.
109 wakeup_candidates.insert(per_address_queue.front());
88 } 110 }
89 } 111 }
112
113 WakeupSocketIfNecessary(wakeup_candidates);
90 } 114 }
91 115
92 void WebSocketThrottle::WakeupSocketIfNecessary() { 116 void WebSocketThrottle::WakeupSocketIfNecessary(
93 for (ConnectingQueue::iterator iter = queue_.begin(); 117 const std::set<WebSocketJob*>& wakeup_candidates) {
94 iter != queue_.end(); 118 for (std::set<WebSocketJob*>::const_iterator iter = wakeup_candidates.begin();
119 iter != wakeup_candidates.end();
95 ++iter) { 120 ++iter) {
96 WebSocketJob* job = *iter; 121 WebSocketJob* job = *iter;
97 if (!job->IsWaiting()) 122 if (!job->IsWaiting())
98 continue; 123 continue;
99 124
100 bool should_wakeup = true; 125 bool should_wakeup = true;
101 const AddressList& address_list = job->address_list(); 126 const AddressList& resolved_address_list = job->address_list();
102 for (AddressList::const_iterator addr_iter = address_list.begin(); 127 for (AddressList::const_iterator addr_iter = resolved_address_list.begin();
103 addr_iter != address_list.end(); 128 addr_iter != resolved_address_list.end();
104 ++addr_iter) { 129 ++addr_iter) {
105 const IPEndPoint& address = *addr_iter; 130 const IPEndPoint& address = *addr_iter;
106 ConnectingAddressMap::iterator map_iter = addr_map_.find(address); 131 ConnectingAddressMap::iterator map_iter = addr_map_.find(address);
107 DCHECK(map_iter != addr_map_.end()); 132 DCHECK(map_iter != addr_map_.end());
108 ConnectingQueue* queue = map_iter->second; 133 const ConnectingQueue& per_address_queue = map_iter->second;
109 if (job != queue->front()) { 134 if (job != per_address_queue.front()) {
110 should_wakeup = false; 135 should_wakeup = false;
111 break; 136 break;
112 } 137 }
113 } 138 }
114 if (should_wakeup) 139 if (should_wakeup)
115 job->Wakeup(); 140 job->Wakeup();
116 } 141 }
117 } 142 }
118 143
119 } // namespace net 144 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_throttle.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698