2323
2424using namespace std ;
2525
26+ #if __cplusplus < 201703L
27+ # include < boost/unordered_map.hpp>
28+ #endif
29+
30+
2631namespace restc_cpp {
2732
2833class ConnectionPoolImpl
@@ -31,35 +36,73 @@ class ConnectionPoolImpl
3136public:
3237
3338 struct Key {
34- Key (boost::asio::ip::tcp::endpoint ep,
35- const Connection::Type connectionType)
36- : endpoint{std::move (ep)}, type{connectionType} {}
39+ Key (boost::asio::ip::tcp::endpoint ep, Connection::Type connectionType)
40+ : endpoint(std::move(ep)), type(connectionType) {}
3741
3842 Key (const Key&) = default ;
3943 Key (Key&&) = default ;
4044 ~Key () = default ;
41- Key& operator = (const Key&) = delete ;
42- Key& operator = (Key&&) = delete ;
45+ Key& operator = (const Key&) = delete ;
46+ Key& operator = (Key&&) = delete ;
4347
44- bool operator < (const Key& key) const {
48+ bool operator < (const Key& key) const {
4549 if (static_cast <int >(type) < static_cast <int >(key.type )) {
4650 return true ;
4751 }
48-
52+ if (static_cast <int >(type) > static_cast <int >(key.type )) {
53+ return false ;
54+ }
4955 return endpoint < key.endpoint ;
5056 }
5157
52- friend std::ostream& operator << (std::ostream& o, const Key& v) {
58+ bool operator ==(const Key& key) const {
59+ return type == key.type && endpoint == key.endpoint ;
60+ }
61+
62+ friend std::ostream& operator <<(std::ostream& o, const Key& v) {
5363 return o << " {Key "
54- << (v.type == Connection::Type::HTTPS ? " https" : " http" )
55- << " ://"
56- << v.endpoint
57- << " }" ;
64+ << (v.type == Connection::Type::HTTPS ? " https" : " http" )
65+ << " ://"
66+ << v.endpoint
67+ << " }" ;
5868 }
5969
70+ // Custom hash function
71+ struct KeyHash {
72+ std::size_t operator ()(const Key& key) const {
73+ std::size_t h1 = 0 ;
74+
75+ // Hash the binary address data
76+ if (key.endpoint .address ().is_v4 ()) {
77+ // IPv4: 4 bytes
78+ const auto addr = key.endpoint .address ().to_v4 ().to_bytes ();
79+ h1 = std::hash<uint32_t >()(*reinterpret_cast <const uint32_t *>(addr.data ()));
80+ } else if (key.endpoint .address ().is_v6 ()) {
81+ // IPv6: 16 bytes
82+ const auto addr = key.endpoint .address ().to_v6 ().to_bytes ();
83+ const uint64_t * parts = reinterpret_cast <const uint64_t *>(addr.data ());
84+ h1 = std::hash<uint64_t >()(parts[0 ]) ^ std::hash<uint64_t >()(parts[1 ]);
85+ }
86+
87+ // Hash the port and type
88+ std::size_t h2 = std::hash<unsigned short >()(key.endpoint .port ());
89+ std::size_t h3 = std::hash<int >()(static_cast <int >(key.type ));
90+
91+ // Combine the hashes
92+ return h1 ^ (h2 << 1 ) ^ (h3 << 2 );
93+ }
94+ };
95+
96+ // Equality comparison for hash table
97+ struct KeyEqual {
98+ bool operator ()(const Key& lhs, const Key& rhs) const {
99+ return lhs == rhs;
100+ }
101+ };
102+
60103 private:
61- const boost::asio::ip::tcp::endpoint endpoint;
62- const Connection::Type type;
104+ boost::asio::ip::tcp::endpoint endpoint;
105+ Connection::Type type;
63106 };
64107
65108 struct Entry {
@@ -400,9 +443,13 @@ class ConnectionPoolImpl
400443#endif
401444 std::once_flag close_once_;
402445 RestClient& owner_;
403- multimap<Key, Entry::ptr_t > idle_;
404- multimap<Key, std::weak_ptr<Entry>> in_use_;
405- // std::queue<Entry> pending_;
446+ #if __cplusplus < 201703L
447+ boost::unordered_multimap<Key, Entry::ptr_t , Key::KeyHash, Key::KeyEqual> idle_;
448+ boost::unordered_multimap<Key, std::weak_ptr<Entry>, Key::KeyHash, Key::KeyEqual> in_use_;
449+ #else
450+ std::unordered_multimap<Key, Entry::ptr_t , Key::KeyHash, Key::KeyEqual> idle_;
451+ std::unordered_multimap<Key, std::weak_ptr<Entry>, Key::KeyHash, Key::KeyEqual> in_use_;
452+ #endif
406453 const Request::Properties::ptr_t properties_;
407454 ConnectionWrapper::release_callback_t on_release_;
408455 boost::asio::deadline_timer cache_cleanup_timer_;
0 commit comments