Chromium Code Reviews| 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 |