| 206 | } |
| 207 | |
| 208 | void Acceptor::ListConnections(std::vector<SocketId>* conn_list, |
| 209 | size_t max_copied) { |
| 210 | if (conn_list == NULL) { |
| 211 | LOG(FATAL) << "Param[conn_list] is NULL"; |
| 212 | return; |
| 213 | } |
| 214 | conn_list->clear(); |
| 215 | // Add additional 10(randomly small number) so that even if |
| 216 | // ConnectionCount is inaccurate, enough space is reserved |
| 217 | conn_list->reserve(ConnectionCount() + 10); |
| 218 | |
| 219 | std::unique_lock<butil::Mutex> mu(_map_mutex); |
| 220 | // Copy all the SocketId (protected by mutex) into a temporary |
| 221 | // container to avoid dealing with sockets inside the mutex. |
| 222 | size_t ntotal = 0; |
| 223 | size_t n = 0; |
| 224 | for (SocketMap::const_iterator it = _socket_map.begin(); |
| 225 | it != _socket_map.end(); ++it, ++ntotal) { |
| 226 | if (ntotal >= max_copied) { |
| 227 | return; |
| 228 | } |
| 229 | if (++n >= 256/*max iterated one pass*/) { |
| 230 | SocketMap::PositionHint hint; |
| 231 | _socket_map.save_iterator(it, &hint); |
| 232 | n = 0; |
| 233 | mu.unlock(); // yield |
| 234 | mu.lock(); |
| 235 | it = _socket_map.restore_iterator(hint); |
| 236 | if (it == _socket_map.begin()) { // resized |
| 237 | conn_list->clear(); |
| 238 | } |
| 239 | if (it == _socket_map.end()) { |
| 240 | break; |
| 241 | } |
| 242 | } |
| 243 | conn_list->push_back(it->first); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | void Acceptor::ListConnections(std::vector<SocketId>* conn_list) { |
| 248 | return ListConnections(conn_list, std::numeric_limits<size_t>::max()); |