| 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 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ | 5 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ |
| 6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ | 6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 // A ClientSocketPool is used to restrict the number of sockets open at a time. | 22 // A ClientSocketPool is used to restrict the number of sockets open at a time. |
| 23 // It also maintains a list of idle persistent sockets. | 23 // It also maintains a list of idle persistent sockets. |
| 24 // | 24 // |
| 25 // The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is | 25 // The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is |
| 26 // not responsible for allocating the associated ClientSocket objects. The | 26 // not responsible for allocating the associated ClientSocket objects. The |
| 27 // consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value. | 27 // consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value. |
| 28 // | 28 // |
| 29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { | 29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { |
| 30 public: | 30 public: |
| 31 explicit ClientSocketPool(int max_sockets_per_group); | 31 // Construct a socket pool with the given limits. |
| 32 // |
| 33 // |max_sockets_per_group|: |
| 34 // The total number of active sockets allowed per "group". |
| 35 // (A "group" generally corresponds with a single host, so this is |
| 36 // effectively the connections-per-host bound). |
| 37 // |
| 38 // |max_sockets|: |
| 39 // The total number of active sockets across all groups. |
| 40 // |
| 41 // TODO(eroman): would be nice to define these in terms of "open" sockets |
| 42 // instead (active + idle). |
| 43 ClientSocketPool(int max_sockets_per_group, int max_sockets); |
| 32 | 44 |
| 33 // Called to request a socket for the given handle. There are three possible | 45 // Called to request a socket for the given handle. There are three possible |
| 34 // results: 1) the handle will be initialized with a socket to reuse, 2) the | 46 // results: 1) the handle will be initialized with a socket to reuse, 2) the |
| 35 // handle will be initialized without a socket such that the consumer needs | 47 // handle will be initialized without a socket such that the consumer needs |
| 36 // to supply a socket, or 3) the handle will be added to a wait list until a | 48 // to supply a socket, or 3) the handle will be added to a wait list until a |
| 37 // socket is available to reuse or the opportunity to create a new socket | 49 // socket is available to reuse or the opportunity to create a new socket |
| 38 // arises. The completion callback is notified in the 3rd case. |priority| | 50 // arises. The completion callback is notified in the 3rd case. |priority| |
| 39 // will determine the placement into the wait list. | 51 // will determine the placement into the wait list. |
| 40 // | 52 // |
| 41 // If this function returns OK, then |handle| is initialized upon return. | 53 // If this function returns OK, then |handle| is initialized upon return. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 | 115 |
| 104 typedef std::deque<Request> RequestQueue; | 116 typedef std::deque<Request> RequestQueue; |
| 105 | 117 |
| 106 // A Group is allocated per group_name when there are idle sockets or pending | 118 // A Group is allocated per group_name when there are idle sockets or pending |
| 107 // requests. Otherwise, the Group object is removed from the map. | 119 // requests. Otherwise, the Group object is removed from the map. |
| 108 struct Group { | 120 struct Group { |
| 109 Group() : active_socket_count(0) {} | 121 Group() : active_socket_count(0) {} |
| 110 std::deque<IdleSocket> idle_sockets; | 122 std::deque<IdleSocket> idle_sockets; |
| 111 RequestQueue pending_requests; | 123 RequestQueue pending_requests; |
| 112 int active_socket_count; | 124 int active_socket_count; |
| 125 |
| 126 bool empty() const { |
| 127 return active_socket_count == 0 && idle_sockets.empty() && |
| 128 pending_requests.empty(); |
| 129 } |
| 113 }; | 130 }; |
| 114 | 131 |
| 115 typedef std::map<std::string, Group> GroupMap; | 132 typedef std::map<std::string, Group> GroupMap; |
| 116 | 133 |
| 117 ~ClientSocketPool(); | 134 ~ClientSocketPool(); |
| 118 | 135 |
| 119 static void InsertRequestIntoQueue(const Request& r, | 136 static void InsertRequestIntoQueue(const Request& r, |
| 120 RequestQueue* pending_requests); | 137 RequestQueue* pending_requests); |
| 121 | 138 |
| 122 // Closes all idle sockets if |force| is true. Else, only closes idle | 139 // Closes all idle sockets if |force| is true. Else, only closes idle |
| 123 // sockets that timed out or can't be reused. | 140 // sockets that timed out or can't be reused. |
| 124 void CleanupIdleSockets(bool force); | 141 void CleanupIdleSockets(bool force); |
| 125 | 142 |
| 126 // Called when the number of idle sockets changes. | 143 // Called when the number of idle sockets changes. |
| 127 void IncrementIdleCount(); | 144 void IncrementIdleCount(); |
| 128 void DecrementIdleCount(); | 145 void DecrementIdleCount(); |
| 129 | 146 |
| 130 // Called via PostTask by ReleaseSocket. | 147 // Called via PostTask by ReleaseSocket. |
| 131 void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); | 148 void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); |
| 132 | 149 |
| 150 // Dequeue and start the highest priority pending request in |group|. |
| 151 void StartPendingRequestForGroup(Group* group); |
| 152 |
| 153 // Finds the group containing the highest priority pending request, and which |
| 154 // has fewer than |max_sockets_per_group_| active sockets. Returns NULL if |
| 155 // there is no such group. |
| 156 Group* FindTopStalledGroup(); |
| 157 |
| 158 // Until the maximum number of sockets limit is reached, a group can ONLY |
| 159 // have pending requests if it exceeds the "max sockets per group" limit. |
| 160 // |
| 161 // This means when a socket is released, the only pending requests that can |
| 162 // be started next belong to the same group. |
| 163 // |
| 164 // However once the |max_sockets_| limit is reached, this stops being true: |
| 165 // groups can now have pending requests without having first reached the |
| 166 // |max_sockets_per_group_| limit. So choosing the next request involves |
| 167 // selecting the highest priority request across *all* groups. |
| 168 // |
| 169 // Since reaching the maximum number of sockets is an edge case, we make note |
| 170 // of when it happens with the following variable, and thus avoid doing |
| 171 // the slower "scan all groups" in the common case. |
| 172 bool may_have_stalled_group_; |
| 173 |
| 133 // Called when timer_ fires. This method scans the idle sockets removing | 174 // Called when timer_ fires. This method scans the idle sockets removing |
| 134 // sockets that timed out or can't be reused. | 175 // sockets that timed out or can't be reused. |
| 135 void OnCleanupTimerFired() { | 176 void OnCleanupTimerFired() { |
| 136 CleanupIdleSockets(false); | 177 CleanupIdleSockets(false); |
| 137 } | 178 } |
| 138 | 179 |
| 139 GroupMap group_map_; | 180 GroupMap group_map_; |
| 140 | 181 |
| 141 // Timer used to periodically prune idle sockets that timed out or can't be | 182 // Timer used to periodically prune idle sockets that timed out or can't be |
| 142 // reused. | 183 // reused. |
| 143 base::RepeatingTimer<ClientSocketPool> timer_; | 184 base::RepeatingTimer<ClientSocketPool> timer_; |
| 144 | 185 |
| 145 // The total number of idle sockets in the system. | 186 // The total number of idle sockets in the system. |
| 146 int idle_socket_count_; | 187 int idle_socket_count_; |
| 147 | 188 |
| 148 // The maximum number of sockets kept per group. | 189 // The total number of active sockets in the system. |
| 190 int active_socket_count_; |
| 191 |
| 192 // The maximum number of active sockets kept per group. |
| 149 int max_sockets_per_group_; | 193 int max_sockets_per_group_; |
| 150 | 194 |
| 195 // The maximum number of active sockets kept across all groups. |
| 196 int max_sockets_; |
| 197 |
| 151 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); | 198 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); |
| 152 }; | 199 }; |
| 153 | 200 |
| 154 } // namespace net | 201 } // namespace net |
| 155 | 202 |
| 156 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ | 203 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ |
| OLD | NEW |