OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // A ClientSocketPoolBase is used to restrict the number of sockets open at | 5 // A ClientSocketPoolBase is used to restrict the number of sockets open at |
6 // a time. It also maintains a list of idle persistent sockets for reuse. | 6 // a time. It also maintains a list of idle persistent sockets for reuse. |
7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle | 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle |
8 // the core logic of (1) restricting the number of active (connected or | 8 // the core logic of (1) restricting the number of active (connected or |
9 // connecting) sockets per "group" (generally speaking, the hostname), (2) | 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) |
10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) | 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) |
11 // limiting the total number of active sockets in the system. | 11 // limiting the total number of active sockets in the system. |
12 // | 12 // |
13 // ClientSocketPoolBase abstracts socket connection details behind ConnectJob, | 13 // ClientSocketPoolBase abstracts socket connection details behind ConnectJob, |
14 // ConnectJobFactory, and SocketParams. When a socket "slot" becomes available, | 14 // ConnectJobFactory, and SocketParams. When a socket "slot" becomes available, |
15 // the ClientSocketPoolBase will ask the ConnectJobFactory to create a | 15 // the ClientSocketPoolBase will ask the ConnectJobFactory to create a |
16 // ConnectJob with a SocketParams. Subclasses of ClientSocketPool should | 16 // ConnectJob with a SocketParams. Subclasses of ClientSocketPool should |
17 // implement their socket specific connection by subclassing ConnectJob and | 17 // implement their socket specific connection by subclassing ConnectJob and |
18 // implementing ConnectJob::ConnectInternal(). They can control the parameters | 18 // implementing ConnectJob::ConnectInternal(). They can control the parameters |
19 // passed to each new ConnectJob instance via their ConnectJobFactory subclass | 19 // passed to each new ConnectJob instance via their ConnectJobFactory subclass |
20 // and templated SocketParams parameter. | 20 // and templated SocketParams parameter. |
21 // | 21 // |
22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
24 #pragma once | 24 #pragma once |
25 | 25 |
26 #include <deque> | 26 #include <deque> |
27 #include <list> | 27 #include <list> |
28 #include <map> | 28 #include <map> |
29 #include <set> | 29 #include <set> |
30 #include <string> | 30 #include <string> |
| 31 #include <vector> |
31 | 32 |
32 #include "base/basictypes.h" | 33 #include "base/basictypes.h" |
33 #include "base/memory/ref_counted.h" | 34 #include "base/memory/ref_counted.h" |
34 #include "base/memory/scoped_ptr.h" | 35 #include "base/memory/scoped_ptr.h" |
35 #include "base/memory/weak_ptr.h" | 36 #include "base/memory/weak_ptr.h" |
36 #include "base/time.h" | 37 #include "base/time.h" |
37 #include "base/timer.h" | 38 #include "base/timer.h" |
38 #include "net/base/address_list.h" | 39 #include "net/base/address_list.h" |
39 #include "net/base/completion_callback.h" | 40 #include "net/base/completion_callback.h" |
40 #include "net/base/load_states.h" | 41 #include "net/base/load_states.h" |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 | 233 |
233 ClientSocketPoolBaseHelper( | 234 ClientSocketPoolBaseHelper( |
234 int max_sockets, | 235 int max_sockets, |
235 int max_sockets_per_group, | 236 int max_sockets_per_group, |
236 base::TimeDelta unused_idle_socket_timeout, | 237 base::TimeDelta unused_idle_socket_timeout, |
237 base::TimeDelta used_idle_socket_timeout, | 238 base::TimeDelta used_idle_socket_timeout, |
238 ConnectJobFactory* connect_job_factory); | 239 ConnectJobFactory* connect_job_factory); |
239 | 240 |
240 virtual ~ClientSocketPoolBaseHelper(); | 241 virtual ~ClientSocketPoolBaseHelper(); |
241 | 242 |
| 243 // Adds/Removes layered pools. It is expected in the destructor that no |
| 244 // layered pools remain. |
| 245 void AddLayeredPool(LayeredPool* pool); |
| 246 void RemoveLayeredPool(LayeredPool* pool); |
| 247 |
242 // See ClientSocketPool::RequestSocket for documentation on this function. | 248 // See ClientSocketPool::RequestSocket for documentation on this function. |
243 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be | 249 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be |
244 // heap allocated. | 250 // heap allocated. |
245 int RequestSocket(const std::string& group_name, const Request* request); | 251 int RequestSocket(const std::string& group_name, const Request* request); |
246 | 252 |
247 // See ClientSocketPool::RequestSocket for documentation on this function. | 253 // See ClientSocketPool::RequestSocket for documentation on this function. |
248 void RequestSockets(const std::string& group_name, | 254 void RequestSockets(const std::string& group_name, |
249 const Request& request, | 255 const Request& request, |
250 int num_sockets); | 256 int num_sockets); |
251 | 257 |
252 // See ClientSocketPool::CancelRequest for documentation on this function. | 258 // See ClientSocketPool::CancelRequest for documentation on this function. |
253 void CancelRequest(const std::string& group_name, | 259 void CancelRequest(const std::string& group_name, |
254 ClientSocketHandle* handle); | 260 ClientSocketHandle* handle); |
255 | 261 |
256 // See ClientSocketPool::ReleaseSocket for documentation on this function. | 262 // See ClientSocketPool::ReleaseSocket for documentation on this function. |
257 void ReleaseSocket(const std::string& group_name, | 263 void ReleaseSocket(const std::string& group_name, |
258 StreamSocket* socket, | 264 StreamSocket* socket, |
259 int id); | 265 int id); |
260 | 266 |
261 // See ClientSocketPool::Flush for documentation on this function. | 267 // See ClientSocketPool::Flush for documentation on this function. |
262 void Flush(); | 268 void Flush(); |
263 | 269 |
| 270 // See ClientSocketPool::IsStalled for documentation on this function. |
| 271 bool IsStalled() const; |
| 272 |
264 // See ClientSocketPool::CloseIdleSockets for documentation on this function. | 273 // See ClientSocketPool::CloseIdleSockets for documentation on this function. |
265 void CloseIdleSockets(); | 274 void CloseIdleSockets(); |
266 | 275 |
267 // See ClientSocketPool::IdleSocketCount() for documentation on this function. | 276 // See ClientSocketPool::IdleSocketCount() for documentation on this function. |
268 int idle_socket_count() const { | 277 int idle_socket_count() const { |
269 return idle_socket_count_; | 278 return idle_socket_count_; |
270 } | 279 } |
271 | 280 |
272 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this | 281 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this |
273 // function. | 282 // function. |
(...skipping 25 matching lines...) Expand all Loading... |
299 // by kCleanupInterval are cleaned up using a timer. Otherwise they are | 308 // by kCleanupInterval are cleaned up using a timer. Otherwise they are |
300 // closed next time client makes a request. This may reduce network | 309 // closed next time client makes a request. This may reduce network |
301 // activity and power consumption. | 310 // activity and power consumption. |
302 static bool cleanup_timer_enabled(); | 311 static bool cleanup_timer_enabled(); |
303 static bool set_cleanup_timer_enabled(bool enabled); | 312 static bool set_cleanup_timer_enabled(bool enabled); |
304 | 313 |
305 // Closes all idle sockets if |force| is true. Else, only closes idle | 314 // Closes all idle sockets if |force| is true. Else, only closes idle |
306 // sockets that timed out or can't be reused. Made public for testing. | 315 // sockets that timed out or can't be reused. Made public for testing. |
307 void CleanupIdleSockets(bool force); | 316 void CleanupIdleSockets(bool force); |
308 | 317 |
| 318 // Closes one idle socket. Picks the first one encountered. |
| 319 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we |
| 320 // should keep an ordered list of idle sockets, and close them in order. |
| 321 // Requires maintaining more state. It's not clear if it's worth it since |
| 322 // I'm not sure if we hit this situation often. |
| 323 bool CloseOneIdleSocket(); |
| 324 |
| 325 // Checks layered pools to see if they can close an idle connection. |
| 326 bool CloseOneIdleConnectionInLayeredPool(); |
| 327 |
309 // See ClientSocketPool::GetInfoAsValue for documentation on this function. | 328 // See ClientSocketPool::GetInfoAsValue for documentation on this function. |
310 base::DictionaryValue* GetInfoAsValue(const std::string& name, | 329 base::DictionaryValue* GetInfoAsValue(const std::string& name, |
311 const std::string& type) const; | 330 const std::string& type) const; |
312 | 331 |
313 base::TimeDelta ConnectionTimeout() const { | 332 base::TimeDelta ConnectionTimeout() const { |
314 return connect_job_factory_->ConnectionTimeout(); | 333 return connect_job_factory_->ConnectionTimeout(); |
315 } | 334 } |
316 | 335 |
317 static bool connect_backup_jobs_enabled(); | 336 static bool connect_backup_jobs_enabled(); |
318 static bool set_connect_backup_jobs_enabled(bool enabled); | 337 static bool set_connect_backup_jobs_enabled(bool enabled); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 | 383 |
365 bool HasAvailableSocketSlot(int max_sockets_per_group) const { | 384 bool HasAvailableSocketSlot(int max_sockets_per_group) const { |
366 return NumActiveSocketSlots() < max_sockets_per_group; | 385 return NumActiveSocketSlots() < max_sockets_per_group; |
367 } | 386 } |
368 | 387 |
369 int NumActiveSocketSlots() const { | 388 int NumActiveSocketSlots() const { |
370 return active_socket_count_ + static_cast<int>(jobs_.size()) + | 389 return active_socket_count_ + static_cast<int>(jobs_.size()) + |
371 static_cast<int>(idle_sockets_.size()); | 390 static_cast<int>(idle_sockets_.size()); |
372 } | 391 } |
373 | 392 |
374 bool IsStalled(int max_sockets_per_group) const { | 393 bool IsStalledOnPoolMaxSockets(int max_sockets_per_group) const { |
375 return HasAvailableSocketSlot(max_sockets_per_group) && | 394 return HasAvailableSocketSlot(max_sockets_per_group) && |
376 pending_requests_.size() > jobs_.size(); | 395 pending_requests_.size() > jobs_.size(); |
377 } | 396 } |
378 | 397 |
379 RequestPriority TopPendingPriority() const { | 398 RequestPriority TopPendingPriority() const { |
380 return pending_requests_.front()->priority(); | 399 return pending_requests_.front()->priority(); |
381 } | 400 } |
382 | 401 |
383 bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); } | 402 bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); } |
384 | 403 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 | 469 |
451 // Called when the number of idle sockets changes. | 470 // Called when the number of idle sockets changes. |
452 void IncrementIdleCount(); | 471 void IncrementIdleCount(); |
453 void DecrementIdleCount(); | 472 void DecrementIdleCount(); |
454 | 473 |
455 // Start cleanup timer for idle sockets. | 474 // Start cleanup timer for idle sockets. |
456 void StartIdleSocketTimer(); | 475 void StartIdleSocketTimer(); |
457 | 476 |
458 // Scans the group map for groups which have an available socket slot and | 477 // Scans the group map for groups which have an available socket slot and |
459 // at least one pending request. Returns true if any groups are stalled, and | 478 // at least one pending request. Returns true if any groups are stalled, and |
460 // if so, fills |group| and |group_name| with data of the stalled group | 479 // if so (and if both |group| and |group_name| are not NULL), fills |group| |
461 // having highest priority. | 480 // and |group_name| with data of the stalled group having highest priority. |
462 bool FindTopStalledGroup(Group** group, std::string* group_name); | 481 bool FindTopStalledGroup(Group** group, std::string* group_name) const; |
463 | 482 |
464 // Called when timer_ fires. This method scans the idle sockets removing | 483 // Called when timer_ fires. This method scans the idle sockets removing |
465 // sockets that timed out or can't be reused. | 484 // sockets that timed out or can't be reused. |
466 void OnCleanupTimerFired() { | 485 void OnCleanupTimerFired() { |
467 CleanupIdleSockets(false); | 486 CleanupIdleSockets(false); |
468 } | 487 } |
469 | 488 |
470 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. | 489 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. |
471 void RemoveConnectJob(ConnectJob* job, Group* group); | 490 void RemoveConnectJob(ConnectJob* job, Group* group); |
472 | 491 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 int RequestSocketInternal(const std::string& group_name, | 523 int RequestSocketInternal(const std::string& group_name, |
505 const Request* request); | 524 const Request* request); |
506 | 525 |
507 // Assigns an idle socket for the group to the request. | 526 // Assigns an idle socket for the group to the request. |
508 // Returns |true| if an idle socket is available, false otherwise. | 527 // Returns |true| if an idle socket is available, false otherwise. |
509 bool AssignIdleSocketToGroup(const Request* request, Group* group); | 528 bool AssignIdleSocketToGroup(const Request* request, Group* group); |
510 | 529 |
511 static void LogBoundConnectJobToRequest( | 530 static void LogBoundConnectJobToRequest( |
512 const NetLog::Source& connect_job_source, const Request* request); | 531 const NetLog::Source& connect_job_source, const Request* request); |
513 | 532 |
514 // Closes one idle socket. Picks the first one encountered. | |
515 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we | |
516 // should keep an ordered list of idle sockets, and close them in order. | |
517 // Requires maintaining more state. It's not clear if it's worth it since | |
518 // I'm not sure if we hit this situation often. | |
519 void CloseOneIdleSocket(); | |
520 | |
521 // Same as CloseOneIdleSocket() except it won't close an idle socket in | 533 // Same as CloseOneIdleSocket() except it won't close an idle socket in |
522 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a | 534 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a |
523 // socket. | 535 // socket. |
524 bool CloseOneIdleSocketExceptInGroup(const Group* group); | 536 bool CloseOneIdleSocketExceptInGroup(const Group* group); |
525 | 537 |
526 // Checks if there are stalled socket groups that should be notified | 538 // Checks if there are stalled socket groups that should be notified |
527 // for possible wakeup. | 539 // for possible wakeup. |
528 void CheckForStalledSocketGroups(); | 540 void CheckForStalledSocketGroups(); |
529 | 541 |
530 // Posts a task to call InvokeUserCallback() on the next iteration through the | 542 // Posts a task to call InvokeUserCallback() on the next iteration through the |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 587 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
576 | 588 |
577 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool | 589 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool |
578 bool connect_backup_jobs_enabled_; | 590 bool connect_backup_jobs_enabled_; |
579 | 591 |
580 // A unique id for the pool. It gets incremented every time we Flush() the | 592 // A unique id for the pool. It gets incremented every time we Flush() the |
581 // pool. This is so that when sockets get released back to the pool, we can | 593 // pool. This is so that when sockets get released back to the pool, we can |
582 // make sure that they are discarded rather than reused. | 594 // make sure that they are discarded rather than reused. |
583 int pool_generation_number_; | 595 int pool_generation_number_; |
584 | 596 |
| 597 std::set<LayeredPool*> higher_layer_pools_; |
| 598 |
585 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; | 599 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; |
586 | 600 |
587 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); | 601 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); |
588 }; | 602 }; |
589 | 603 |
590 } // namespace internal | 604 } // namespace internal |
591 | 605 |
592 template <typename SocketParams> | 606 template <typename SocketParams> |
593 class ClientSocketPoolBase { | 607 class ClientSocketPoolBase { |
594 public: | 608 public: |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 base::TimeDelta used_idle_socket_timeout, | 655 base::TimeDelta used_idle_socket_timeout, |
642 ConnectJobFactory* connect_job_factory) | 656 ConnectJobFactory* connect_job_factory) |
643 : histograms_(histograms), | 657 : histograms_(histograms), |
644 helper_(max_sockets, max_sockets_per_group, | 658 helper_(max_sockets, max_sockets_per_group, |
645 unused_idle_socket_timeout, used_idle_socket_timeout, | 659 unused_idle_socket_timeout, used_idle_socket_timeout, |
646 new ConnectJobFactoryAdaptor(connect_job_factory)) {} | 660 new ConnectJobFactoryAdaptor(connect_job_factory)) {} |
647 | 661 |
648 virtual ~ClientSocketPoolBase() {} | 662 virtual ~ClientSocketPoolBase() {} |
649 | 663 |
650 // These member functions simply forward to ClientSocketPoolBaseHelper. | 664 // These member functions simply forward to ClientSocketPoolBaseHelper. |
| 665 void AddLayeredPool(LayeredPool* pool) { |
| 666 helper_.AddLayeredPool(pool); |
| 667 } |
| 668 |
| 669 void RemoveLayeredPool(LayeredPool* pool) { |
| 670 helper_.RemoveLayeredPool(pool); |
| 671 } |
651 | 672 |
652 // RequestSocket bundles up the parameters into a Request and then forwards to | 673 // RequestSocket bundles up the parameters into a Request and then forwards to |
653 // ClientSocketPoolBaseHelper::RequestSocket(). | 674 // ClientSocketPoolBaseHelper::RequestSocket(). |
654 int RequestSocket(const std::string& group_name, | 675 int RequestSocket(const std::string& group_name, |
655 const scoped_refptr<SocketParams>& params, | 676 const scoped_refptr<SocketParams>& params, |
656 RequestPriority priority, | 677 RequestPriority priority, |
657 ClientSocketHandle* handle, | 678 ClientSocketHandle* handle, |
658 const CompletionCallback& callback, | 679 const CompletionCallback& callback, |
659 const BoundNetLog& net_log) { | 680 const BoundNetLog& net_log) { |
660 Request* request = | 681 Request* request = |
(...skipping 24 matching lines...) Expand all Loading... |
685 void CancelRequest(const std::string& group_name, | 706 void CancelRequest(const std::string& group_name, |
686 ClientSocketHandle* handle) { | 707 ClientSocketHandle* handle) { |
687 return helper_.CancelRequest(group_name, handle); | 708 return helper_.CancelRequest(group_name, handle); |
688 } | 709 } |
689 | 710 |
690 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, | 711 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, |
691 int id) { | 712 int id) { |
692 return helper_.ReleaseSocket(group_name, socket, id); | 713 return helper_.ReleaseSocket(group_name, socket, id); |
693 } | 714 } |
694 | 715 |
| 716 void Flush() { helper_.Flush(); } |
| 717 |
| 718 bool IsStalled() const { return helper_.IsStalled(); } |
| 719 |
695 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } | 720 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } |
696 | 721 |
697 int idle_socket_count() const { return helper_.idle_socket_count(); } | 722 int idle_socket_count() const { return helper_.idle_socket_count(); } |
698 | 723 |
699 int IdleSocketCountInGroup(const std::string& group_name) const { | 724 int IdleSocketCountInGroup(const std::string& group_name) const { |
700 return helper_.IdleSocketCountInGroup(group_name); | 725 return helper_.IdleSocketCountInGroup(group_name); |
701 } | 726 } |
702 | 727 |
703 LoadState GetLoadState(const std::string& group_name, | 728 LoadState GetLoadState(const std::string& group_name, |
704 const ClientSocketHandle* handle) const { | 729 const ClientSocketHandle* handle) const { |
(...skipping 28 matching lines...) Expand all Loading... |
733 base::TimeDelta ConnectionTimeout() const { | 758 base::TimeDelta ConnectionTimeout() const { |
734 return helper_.ConnectionTimeout(); | 759 return helper_.ConnectionTimeout(); |
735 } | 760 } |
736 | 761 |
737 ClientSocketPoolHistograms* histograms() const { | 762 ClientSocketPoolHistograms* histograms() const { |
738 return histograms_; | 763 return histograms_; |
739 } | 764 } |
740 | 765 |
741 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } | 766 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } |
742 | 767 |
743 void Flush() { helper_.Flush(); } | 768 bool CloseOneIdleSocket() { return helper_.CloseOneIdleSocket(); } |
| 769 |
| 770 bool CloseOneIdleConnectionInLayeredPool() { |
| 771 return helper_.CloseOneIdleConnectionInLayeredPool(); |
| 772 } |
744 | 773 |
745 private: | 774 private: |
746 // This adaptor class exists to bridge the | 775 // This adaptor class exists to bridge the |
747 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 776 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
748 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 777 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
749 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 778 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
750 // static_cast themselves. | 779 // static_cast themselves. |
751 class ConnectJobFactoryAdaptor | 780 class ConnectJobFactoryAdaptor |
752 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 781 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
753 public: | 782 public: |
(...skipping 23 matching lines...) Expand all Loading... |
777 // Histograms for the pool | 806 // Histograms for the pool |
778 ClientSocketPoolHistograms* const histograms_; | 807 ClientSocketPoolHistograms* const histograms_; |
779 internal::ClientSocketPoolBaseHelper helper_; | 808 internal::ClientSocketPoolBaseHelper helper_; |
780 | 809 |
781 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 810 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
782 }; | 811 }; |
783 | 812 |
784 } // namespace net | 813 } // namespace net |
785 | 814 |
786 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 815 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |