23
23
24
24
using namespace std ;
25
25
26
+ #if __cplusplus < 201703L
27
+ # include < boost/unordered_map.hpp>
28
+ #endif
29
+
30
+
26
31
namespace restc_cpp {
27
32
28
33
class ConnectionPoolImpl
@@ -31,35 +36,73 @@ class ConnectionPoolImpl
31
36
public:
32
37
33
38
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) {}
37
41
38
42
Key (const Key&) = default ;
39
43
Key (Key&&) = default ;
40
44
~Key () = default ;
41
- Key& operator = (const Key&) = delete ;
42
- Key& operator = (Key&&) = delete ;
45
+ Key& operator = (const Key&) = delete ;
46
+ Key& operator = (Key&&) = delete ;
43
47
44
- bool operator < (const Key& key) const {
48
+ bool operator < (const Key& key) const {
45
49
if (static_cast <int >(type) < static_cast <int >(key.type )) {
46
50
return true ;
47
51
}
48
-
52
+ if (static_cast <int >(type) > static_cast <int >(key.type )) {
53
+ return false ;
54
+ }
49
55
return endpoint < key.endpoint ;
50
56
}
51
57
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) {
53
63
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
+ << " }" ;
58
68
}
59
69
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
+
60
103
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;
63
106
};
64
107
65
108
struct Entry {
@@ -400,9 +443,13 @@ class ConnectionPoolImpl
400
443
#endif
401
444
std::once_flag close_once_;
402
445
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
406
453
const Request::Properties::ptr_t properties_;
407
454
ConnectionWrapper::release_callback_t on_release_;
408
455
boost::asio::deadline_timer cache_cleanup_timer_;
0 commit comments