OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/base/tcp_client_socket_pool.h" | 5 #include "net/base/tcp_client_socket_pool.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/field_trial.h" | 8 #include "base/field_trial.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
(...skipping 29 matching lines...) Expand all Loading... | |
40 ClientSocketFactory* client_socket_factory, | 40 ClientSocketFactory* client_socket_factory, |
41 TCPClientSocketPool* pool) | 41 TCPClientSocketPool* pool) |
42 : group_name_(group_name), | 42 : group_name_(group_name), |
43 handle_(handle), | 43 handle_(handle), |
44 client_socket_factory_(client_socket_factory), | 44 client_socket_factory_(client_socket_factory), |
45 ALLOW_THIS_IN_INITIALIZER_LIST( | 45 ALLOW_THIS_IN_INITIALIZER_LIST( |
46 callback_(this, | 46 callback_(this, |
47 &TCPClientSocketPool::ConnectingSocket::OnIOComplete)), | 47 &TCPClientSocketPool::ConnectingSocket::OnIOComplete)), |
48 pool_(pool), | 48 pool_(pool), |
49 canceled_(false) { | 49 canceled_(false) { |
50 DCHECK(!ContainsKey(pool_->connecting_socket_map_, handle)); | 50 CHECK(!ContainsKey(pool_->connecting_socket_map_, handle)); |
51 pool_->connecting_socket_map_[handle] = this; | 51 pool_->connecting_socket_map_[handle] = this; |
52 } | 52 } |
53 | 53 |
54 TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() { | 54 TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() { |
55 if (!canceled_) | 55 if (!canceled_) |
56 pool_->connecting_socket_map_.erase(handle_); | 56 pool_->connecting_socket_map_.erase(handle_); |
57 } | 57 } |
58 | 58 |
59 int TCPClientSocketPool::ConnectingSocket::Connect( | 59 int TCPClientSocketPool::ConnectingSocket::Connect( |
60 const std::string& host, | 60 const std::string& host, |
61 int port) { | 61 int port) { |
62 DCHECK(!canceled_); | 62 CHECK(!canceled_); |
63 DidStartDnsResolution(host, this); | 63 DidStartDnsResolution(host, this); |
64 int rv = resolver_.Resolve(host, port, &addresses_, &callback_); | 64 int rv = resolver_.Resolve(host, port, &addresses_, &callback_); |
65 if (rv != ERR_IO_PENDING) | 65 if (rv != ERR_IO_PENDING) |
66 rv = OnIOCompleteInternal(rv, true /* synchronous */); | 66 rv = OnIOCompleteInternal(rv, true /* synchronous */); |
67 return rv; | 67 return rv; |
68 } | 68 } |
69 | 69 |
70 void TCPClientSocketPool::ConnectingSocket::OnIOComplete(int result) { | 70 void TCPClientSocketPool::ConnectingSocket::OnIOComplete(int result) { |
71 OnIOCompleteInternal(result, false /* asynchronous */); | 71 OnIOCompleteInternal(result, false /* asynchronous */); |
72 } | 72 } |
73 | 73 |
74 int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal( | 74 int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal( |
75 int result, bool synchronous) { | 75 int result, bool synchronous) { |
76 DCHECK_NE(result, ERR_IO_PENDING); | 76 CHECK(result != ERR_IO_PENDING); |
77 | 77 |
78 if (canceled_) { | 78 if (canceled_) { |
79 // We got canceled, so bail out. | 79 // We got canceled, so bail out. |
80 delete this; | 80 delete this; |
81 return result; | 81 return result; |
82 } | 82 } |
83 | 83 |
84 GroupMap::iterator group_it = pool_->group_map_.find(group_name_); | 84 GroupMap::iterator group_it = pool_->group_map_.find(group_name_); |
85 if (group_it == pool_->group_map_.end()) { | 85 if (group_it == pool_->group_map_.end()) { |
86 // The request corresponding to this ConnectingSocket has been canceled. | 86 // The request corresponding to this ConnectingSocket has been canceled. |
(...skipping 16 matching lines...) Expand all Loading... | |
103 if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) { | 103 if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) { |
104 it->second.load_state = LOAD_STATE_CONNECTING; | 104 it->second.load_state = LOAD_STATE_CONNECTING; |
105 socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_)); | 105 socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_)); |
106 connect_start_time_ = base::Time::Now(); | 106 connect_start_time_ = base::Time::Now(); |
107 result = socket_->Connect(&callback_); | 107 result = socket_->Connect(&callback_); |
108 if (result == ERR_IO_PENDING) | 108 if (result == ERR_IO_PENDING) |
109 return result; | 109 return result; |
110 } | 110 } |
111 | 111 |
112 if (result == OK) { | 112 if (result == OK) { |
113 DCHECK(connect_start_time_ != base::Time()); | 113 CHECK(connect_start_time_ != base::Time()); |
114 base::TimeDelta connect_duration = | 114 base::TimeDelta connect_duration = |
115 base::Time::Now() - connect_start_time_; | 115 base::Time::Now() - connect_start_time_; |
116 | 116 |
117 UMA_HISTOGRAM_CLIPPED_TIMES( | 117 UMA_HISTOGRAM_CLIPPED_TIMES( |
118 FieldTrial::MakeName( | 118 FieldTrial::MakeName( |
119 "Net.TCP_Connection_Latency", "DnsImpact").data(), | 119 "Net.TCP_Connection_Latency", "DnsImpact").data(), |
120 connect_duration, | 120 connect_duration, |
121 base::TimeDelta::FromMilliseconds(1), | 121 base::TimeDelta::FromMilliseconds(1), |
122 base::TimeDelta::FromMinutes(10), | 122 base::TimeDelta::FromMinutes(10), |
123 100); | 123 100); |
124 } | 124 } |
125 | 125 |
126 // Now, we either succeeded at Connect()'ing, or we failed at host resolution | 126 // Now, we either succeeded at Connect()'ing, or we failed at host resolution |
127 // or Connect()'ing. Either way, we'll run the callback to alert the client. | 127 // or Connect()'ing. Either way, we'll run the callback to alert the client. |
128 | 128 |
129 Request request = it->second; | 129 Request request = it->second; |
130 request_map->erase(it); | 130 request_map->erase(it); |
131 | 131 |
132 if (result == OK) { | 132 if (result == OK) { |
133 request.handle->set_socket(socket_.release()); | 133 request.handle->set_socket(socket_.release()); |
134 request.handle->set_is_reused(false); | 134 request.handle->set_is_reused(false); |
135 } else { | 135 } else { |
136 group.active_socket_count--; | 136 group.active_socket_count--; |
137 | 137 |
138 // Delete group if no longer needed. | 138 // Delete group if no longer needed. |
139 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { | 139 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { |
140 DCHECK(group.pending_requests.empty()); | 140 CHECK(group.pending_requests.empty()); |
141 DCHECK(group.connecting_requests.empty()); | 141 CHECK(group.connecting_requests.empty()); |
142 pool_->group_map_.erase(group_it); | 142 pool_->group_map_.erase(group_it); |
143 } | 143 } |
144 } | 144 } |
145 | 145 |
146 if (!synchronous) | 146 if (!synchronous) |
147 request.callback->Run(result); | 147 request.callback->Run(result); |
148 delete this; | 148 delete this; |
149 return result; | 149 return result; |
150 } | 150 } |
151 | 151 |
152 void TCPClientSocketPool::ConnectingSocket::Cancel() { | 152 void TCPClientSocketPool::ConnectingSocket::Cancel() { |
153 DCHECK(!canceled_); | 153 CHECK(!canceled_); |
154 DCHECK(ContainsKey(pool_->connecting_socket_map_, handle_)); | 154 CHECK(ContainsKey(pool_->connecting_socket_map_, handle_)); |
155 pool_->connecting_socket_map_.erase(handle_); | 155 pool_->connecting_socket_map_.erase(handle_); |
156 canceled_ = true; | 156 canceled_ = true; |
157 } | 157 } |
158 | 158 |
159 TCPClientSocketPool::TCPClientSocketPool( | 159 TCPClientSocketPool::TCPClientSocketPool( |
160 int max_sockets_per_group, | 160 int max_sockets_per_group, |
161 ClientSocketFactory* client_socket_factory) | 161 ClientSocketFactory* client_socket_factory) |
162 : client_socket_factory_(client_socket_factory), | 162 : client_socket_factory_(client_socket_factory), |
163 idle_socket_count_(0), | 163 idle_socket_count_(0), |
164 max_sockets_per_group_(max_sockets_per_group) { | 164 max_sockets_per_group_(max_sockets_per_group) { |
(...skipping 27 matching lines...) Expand all Loading... | |
192 ClientSocketHandle* handle, | 192 ClientSocketHandle* handle, |
193 CompletionCallback* callback) { | 193 CompletionCallback* callback) { |
194 DCHECK(!host.empty()); | 194 DCHECK(!host.empty()); |
195 DCHECK_GE(priority, 0); | 195 DCHECK_GE(priority, 0); |
196 Group& group = group_map_[group_name]; | 196 Group& group = group_map_[group_name]; |
197 | 197 |
198 // Can we make another active socket now? | 198 // Can we make another active socket now? |
199 if (group.active_socket_count == max_sockets_per_group_) { | 199 if (group.active_socket_count == max_sockets_per_group_) { |
200 Request r; | 200 Request r; |
201 r.handle = handle; | 201 r.handle = handle; |
202 DCHECK(callback); | 202 CHECK(callback); |
203 r.callback = callback; | 203 r.callback = callback; |
204 r.priority = priority; | 204 r.priority = priority; |
205 r.host = host; | 205 r.host = host; |
206 r.port = port; | 206 r.port = port; |
207 r.load_state = LOAD_STATE_IDLE; | 207 r.load_state = LOAD_STATE_IDLE; |
208 InsertRequestIntoQueue(r, &group.pending_requests); | 208 InsertRequestIntoQueue(r, &group.pending_requests); |
209 return ERR_IO_PENDING; | 209 return ERR_IO_PENDING; |
210 } | 210 } |
211 | 211 |
212 // OK, we are going to activate one. | 212 // OK, we are going to activate one. |
(...skipping 15 matching lines...) Expand all Loading... | |
228 // We couldn't find a socket to reuse, so allocate and connect a new one. | 228 // We couldn't find a socket to reuse, so allocate and connect a new one. |
229 | 229 |
230 // First, we need to make sure we aren't already servicing a request for this | 230 // First, we need to make sure we aren't already servicing a request for this |
231 // handle (which could happen if we requested, canceled, and then requested | 231 // handle (which could happen if we requested, canceled, and then requested |
232 // with the same handle). | 232 // with the same handle). |
233 if (ContainsKey(connecting_socket_map_, handle)) | 233 if (ContainsKey(connecting_socket_map_, handle)) |
234 connecting_socket_map_[handle]->Cancel(); | 234 connecting_socket_map_[handle]->Cancel(); |
235 | 235 |
236 Request r; | 236 Request r; |
237 r.handle = handle; | 237 r.handle = handle; |
238 DCHECK(callback); | 238 CHECK(callback); |
239 r.callback = callback; | 239 r.callback = callback; |
240 r.priority = priority; | 240 r.priority = priority; |
241 r.host = host; | 241 r.host = host; |
242 r.port = port; | 242 r.port = port; |
243 r.load_state = LOAD_STATE_RESOLVING_HOST; | 243 r.load_state = LOAD_STATE_RESOLVING_HOST; |
244 group_map_[group_name].connecting_requests[handle] = r; | 244 group_map_[group_name].connecting_requests[handle] = r; |
245 | 245 |
246 // connecting_socket will delete itself. | 246 // connecting_socket will delete itself. |
247 ConnectingSocket* connecting_socket = | 247 ConnectingSocket* connecting_socket = |
248 new ConnectingSocket(group_name, handle, client_socket_factory_, this); | 248 new ConnectingSocket(group_name, handle, client_socket_factory_, this); |
249 int rv = connecting_socket->Connect(host, port); | 249 int rv = connecting_socket->Connect(host, port); |
250 return rv; | 250 return rv; |
251 } | 251 } |
252 | 252 |
253 void TCPClientSocketPool::CancelRequest(const std::string& group_name, | 253 void TCPClientSocketPool::CancelRequest(const std::string& group_name, |
254 const ClientSocketHandle* handle) { | 254 const ClientSocketHandle* handle) { |
255 DCHECK(ContainsKey(group_map_, group_name)); | 255 CHECK(ContainsKey(group_map_, group_name)); |
256 | 256 |
257 Group& group = group_map_[group_name]; | 257 Group& group = group_map_[group_name]; |
258 | 258 |
259 // Search pending_requests for matching handle. | 259 // Search pending_requests for matching handle. |
260 RequestQueue::iterator it = group.pending_requests.begin(); | 260 RequestQueue::iterator it = group.pending_requests.begin(); |
261 for (; it != group.pending_requests.end(); ++it) { | 261 for (; it != group.pending_requests.end(); ++it) { |
262 if (it->handle == handle) { | 262 if (it->handle == handle) { |
263 group.pending_requests.erase(it); | 263 group.pending_requests.erase(it); |
264 return; | 264 return; |
265 } | 265 } |
266 } | 266 } |
267 | 267 |
268 // It's invalid to cancel a non-existent request. | 268 // It's invalid to cancel a non-existent request. |
269 DCHECK(ContainsKey(group.connecting_requests, handle)); | 269 CHECK(ContainsKey(group.connecting_requests, handle)); |
270 | 270 |
271 RequestMap::iterator map_it = group.connecting_requests.find(handle); | 271 RequestMap::iterator map_it = group.connecting_requests.find(handle); |
272 if (map_it != group.connecting_requests.end()) { | 272 if (map_it != group.connecting_requests.end()) { |
273 group.connecting_requests.erase(map_it); | 273 group.connecting_requests.erase(map_it); |
274 group.active_socket_count--; | 274 group.active_socket_count--; |
275 | 275 |
276 // Delete group if no longer needed. | 276 // Delete group if no longer needed. |
277 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { | 277 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { |
278 DCHECK(group.pending_requests.empty()); | 278 CHECK(group.pending_requests.empty()); |
279 DCHECK(group.connecting_requests.empty()); | 279 CHECK(group.connecting_requests.empty()); |
280 group_map_.erase(group_name); | 280 group_map_.erase(group_name); |
281 } | 281 } |
282 } | 282 } |
283 } | 283 } |
284 | 284 |
285 void TCPClientSocketPool::ReleaseSocket(const std::string& group_name, | 285 void TCPClientSocketPool::ReleaseSocket(const std::string& group_name, |
286 ClientSocket* socket) { | 286 ClientSocket* socket) { |
287 // Run this asynchronously to allow the caller to finish before we let | 287 // Run this asynchronously to allow the caller to finish before we let |
288 // another to begin doing work. This also avoids nasty recursion issues. | 288 // another to begin doing work. This also avoids nasty recursion issues. |
289 // NOTE: We cannot refer to the handle argument after this method returns. | 289 // NOTE: We cannot refer to the handle argument after this method returns. |
290 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 290 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
291 this, &TCPClientSocketPool::DoReleaseSocket, group_name, socket)); | 291 this, &TCPClientSocketPool::DoReleaseSocket, group_name, socket)); |
292 } | 292 } |
293 | 293 |
294 void TCPClientSocketPool::CloseIdleSockets() { | 294 void TCPClientSocketPool::CloseIdleSockets() { |
295 CleanupIdleSockets(true); | 295 CleanupIdleSockets(true); |
296 } | 296 } |
297 | 297 |
298 int TCPClientSocketPool::IdleSocketCountInGroup( | 298 int TCPClientSocketPool::IdleSocketCountInGroup( |
299 const std::string& group_name) const { | 299 const std::string& group_name) const { |
300 GroupMap::const_iterator i = group_map_.find(group_name); | 300 GroupMap::const_iterator i = group_map_.find(group_name); |
301 DCHECK(i != group_map_.end()); | 301 CHECK(i != group_map_.end()); |
302 | 302 |
303 return i->second.idle_sockets.size(); | 303 return i->second.idle_sockets.size(); |
304 } | 304 } |
305 | 305 |
306 LoadState TCPClientSocketPool::GetLoadState( | 306 LoadState TCPClientSocketPool::GetLoadState( |
307 const std::string& group_name, | 307 const std::string& group_name, |
308 const ClientSocketHandle* handle) const { | 308 const ClientSocketHandle* handle) const { |
309 DCHECK(ContainsKey(group_map_, group_name)) << group_name; | 309 if (!ContainsKey(group_map_, group_name)) { |
310 NOTREACHED() << "ClientSocketPool does not contain group: " << group_name | |
wtc
2009/06/11 23:58:19
NOTREACHED is a DCHECK.
willchan no longer on Chromium
2009/06/12 00:23:54
i know it's a DCHECK. i want to keep it as a DCHE
| |
311 << " for handle: " << handle; | |
312 return LOAD_STATE_IDLE; | |
313 } | |
310 | 314 |
311 // Can't use operator[] since it is non-const. | 315 // Can't use operator[] since it is non-const. |
312 const Group& group = group_map_.find(group_name)->second; | 316 const Group& group = group_map_.find(group_name)->second; |
313 | 317 |
314 // Search connecting_requests for matching handle. | 318 // Search connecting_requests for matching handle. |
315 RequestMap::const_iterator map_it = group.connecting_requests.find(handle); | 319 RequestMap::const_iterator map_it = group.connecting_requests.find(handle); |
316 if (map_it != group.connecting_requests.end()) { | 320 if (map_it != group.connecting_requests.end()) { |
317 const LoadState load_state = map_it->second.load_state; | 321 const LoadState load_state = map_it->second.load_state; |
318 DCHECK(load_state == LOAD_STATE_RESOLVING_HOST || | 322 CHECK(load_state == LOAD_STATE_RESOLVING_HOST || |
319 load_state == LOAD_STATE_CONNECTING); | 323 load_state == LOAD_STATE_CONNECTING); |
320 return load_state; | 324 return load_state; |
321 } | 325 } |
322 | 326 |
323 // Search pending_requests for matching handle. | 327 // Search pending_requests for matching handle. |
324 RequestQueue::const_iterator it = group.pending_requests.begin(); | 328 RequestQueue::const_iterator it = group.pending_requests.begin(); |
325 for (; it != group.pending_requests.end(); ++it) { | 329 for (; it != group.pending_requests.end(); ++it) { |
326 if (it->handle == handle) { | 330 if (it->handle == handle) { |
327 DCHECK_EQ(LOAD_STATE_IDLE, it->load_state); | 331 CHECK(LOAD_STATE_IDLE == it->load_state); |
328 // TODO(wtc): Add a state for being on the wait list. | 332 // TODO(wtc): Add a state for being on the wait list. |
329 // See http://www.crbug.com/5077. | 333 // See http://www.crbug.com/5077. |
330 return LOAD_STATE_IDLE; | 334 return LOAD_STATE_IDLE; |
331 } | 335 } |
332 } | 336 } |
333 | 337 |
334 NOTREACHED(); | 338 NOTREACHED(); |
335 return LOAD_STATE_IDLE; | 339 return LOAD_STATE_IDLE; |
336 } | 340 } |
337 | 341 |
(...skipping 21 matching lines...) Expand all Loading... | |
359 delete j->socket; | 363 delete j->socket; |
360 j = group.idle_sockets.erase(j); | 364 j = group.idle_sockets.erase(j); |
361 DecrementIdleCount(); | 365 DecrementIdleCount(); |
362 } else { | 366 } else { |
363 ++j; | 367 ++j; |
364 } | 368 } |
365 } | 369 } |
366 | 370 |
367 // Delete group if no longer needed. | 371 // Delete group if no longer needed. |
368 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { | 372 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { |
369 DCHECK(group.pending_requests.empty()); | 373 CHECK(group.pending_requests.empty()); |
370 DCHECK(group.connecting_requests.empty()); | 374 CHECK(group.connecting_requests.empty()); |
371 group_map_.erase(i++); | 375 group_map_.erase(i++); |
372 } else { | 376 } else { |
373 ++i; | 377 ++i; |
374 } | 378 } |
375 } | 379 } |
376 } | 380 } |
377 | 381 |
378 void TCPClientSocketPool::IncrementIdleCount() { | 382 void TCPClientSocketPool::IncrementIdleCount() { |
379 if (++idle_socket_count_ == 1) | 383 if (++idle_socket_count_ == 1) |
380 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, | 384 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, |
381 &TCPClientSocketPool::OnCleanupTimerFired); | 385 &TCPClientSocketPool::OnCleanupTimerFired); |
382 } | 386 } |
383 | 387 |
384 void TCPClientSocketPool::DecrementIdleCount() { | 388 void TCPClientSocketPool::DecrementIdleCount() { |
385 if (--idle_socket_count_ == 0) | 389 if (--idle_socket_count_ == 0) |
386 timer_.Stop(); | 390 timer_.Stop(); |
387 } | 391 } |
388 | 392 |
389 void TCPClientSocketPool::DoReleaseSocket(const std::string& group_name, | 393 void TCPClientSocketPool::DoReleaseSocket(const std::string& group_name, |
390 ClientSocket* socket) { | 394 ClientSocket* socket) { |
391 GroupMap::iterator i = group_map_.find(group_name); | 395 GroupMap::iterator i = group_map_.find(group_name); |
392 DCHECK(i != group_map_.end()); | 396 CHECK(i != group_map_.end()); |
393 | 397 |
394 Group& group = i->second; | 398 Group& group = i->second; |
395 | 399 |
396 DCHECK_GT(group.active_socket_count, 0); | 400 CHECK(group.active_socket_count > 0); |
397 group.active_socket_count--; | 401 group.active_socket_count--; |
398 | 402 |
399 const bool can_reuse = socket->IsConnectedAndIdle(); | 403 const bool can_reuse = socket->IsConnectedAndIdle(); |
400 if (can_reuse) { | 404 if (can_reuse) { |
401 IdleSocket idle_socket; | 405 IdleSocket idle_socket; |
402 idle_socket.socket = socket; | 406 idle_socket.socket = socket; |
403 idle_socket.start_time = base::TimeTicks::Now(); | 407 idle_socket.start_time = base::TimeTicks::Now(); |
404 | 408 |
405 group.idle_sockets.push_back(idle_socket); | 409 group.idle_sockets.push_back(idle_socket); |
406 IncrementIdleCount(); | 410 IncrementIdleCount(); |
407 } else { | 411 } else { |
408 delete socket; | 412 delete socket; |
409 } | 413 } |
410 | 414 |
411 // Process one pending request. | 415 // Process one pending request. |
412 if (!group.pending_requests.empty()) { | 416 if (!group.pending_requests.empty()) { |
413 Request r = group.pending_requests.front(); | 417 Request r = group.pending_requests.front(); |
414 group.pending_requests.pop_front(); | 418 group.pending_requests.pop_front(); |
415 | 419 |
416 int rv = RequestSocket( | 420 int rv = RequestSocket( |
417 group_name, r.host, r.port, r.priority, r.handle, r.callback); | 421 group_name, r.host, r.port, r.priority, r.handle, r.callback); |
418 if (rv != ERR_IO_PENDING) | 422 if (rv != ERR_IO_PENDING) |
419 r.callback->Run(rv); | 423 r.callback->Run(rv); |
420 return; | 424 return; |
421 } | 425 } |
422 | 426 |
423 // Delete group if no longer needed. | 427 // Delete group if no longer needed. |
424 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { | 428 if (group.active_socket_count == 0 && group.idle_sockets.empty()) { |
425 DCHECK(group.pending_requests.empty()); | 429 CHECK(group.pending_requests.empty()); |
426 DCHECK(group.connecting_requests.empty()); | 430 CHECK(group.connecting_requests.empty()); |
427 group_map_.erase(i); | 431 group_map_.erase(i); |
428 } | 432 } |
429 } | 433 } |
430 | 434 |
431 } // namespace net | 435 } // namespace net |
OLD | NEW |