Skip to content

Commit 1e8e6da

Browse files
committed
Switched std::multimap to std::unordered_multimap to fix runtime error observed under Windows.
1 parent 31f2fa2 commit 1e8e6da

File tree

2 files changed

+55
-17
lines changed

2 files changed

+55
-17
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
55
endif()
66

77
if (NOT DEFINED RESTC_CPP_VERSION)
8-
set(RESTC_CPP_VERSION 0.102.1)
8+
set(RESTC_CPP_VERSION 0.102.2)
99
endif()
1010

1111
if(NOT DEFINED RESTC_BOOST_VERSION)

src/ConnectionPoolImpl.cpp

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,73 @@ class ConnectionPoolImpl
3131
public:
3232

3333
struct Key {
34-
Key(boost::asio::ip::tcp::endpoint ep,
35-
const Connection::Type connectionType)
36-
: endpoint{std::move(ep)}, type{connectionType} {}
34+
Key(boost::asio::ip::tcp::endpoint ep, Connection::Type connectionType)
35+
: endpoint(std::move(ep)), type(connectionType) {}
3736

3837
Key(const Key&) = default;
3938
Key(Key&&) = default;
4039
~Key() = default;
41-
Key& operator = (const Key&) = delete;
42-
Key& operator = (Key&&) = delete;
40+
Key& operator=(const Key&) = delete;
41+
Key& operator=(Key&&) = delete;
4342

44-
bool operator < (const Key& key) const {
43+
bool operator<(const Key& key) const {
4544
if (static_cast<int>(type) < static_cast<int>(key.type)) {
4645
return true;
4746
}
48-
47+
if (static_cast<int>(type) > static_cast<int>(key.type)) {
48+
return false;
49+
}
4950
return endpoint < key.endpoint;
5051
}
5152

52-
friend std::ostream& operator << (std::ostream& o, const Key& v) {
53+
bool operator==(const Key& key) const {
54+
return type == key.type && endpoint == key.endpoint;
55+
}
56+
57+
friend std::ostream& operator<<(std::ostream& o, const Key& v) {
5358
return o << "{Key "
54-
<< (v.type == Connection::Type::HTTPS? "https" : "http")
55-
<< "://"
56-
<< v.endpoint
57-
<< "}";
59+
<< (v.type == Connection::Type::HTTPS ? "https" : "http")
60+
<< "://"
61+
<< v.endpoint
62+
<< "}";
5863
}
5964

65+
// Custom hash function
66+
struct KeyHash {
67+
std::size_t operator()(const Key& key) const {
68+
std::size_t h1 = 0;
69+
70+
// Hash the binary address data
71+
if (key.endpoint.address().is_v4()) {
72+
// IPv4: 4 bytes
73+
const auto addr = key.endpoint.address().to_v4().to_bytes();
74+
h1 = std::hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(addr.data()));
75+
} else if (key.endpoint.address().is_v6()) {
76+
// IPv6: 16 bytes
77+
const auto addr = key.endpoint.address().to_v6().to_bytes();
78+
const uint64_t* parts = reinterpret_cast<const uint64_t*>(addr.data());
79+
h1 = std::hash<uint64_t>()(parts[0]) ^ std::hash<uint64_t>()(parts[1]);
80+
}
81+
82+
// Hash the port and type
83+
std::size_t h2 = std::hash<unsigned short>()(key.endpoint.port());
84+
std::size_t h3 = std::hash<int>()(static_cast<int>(key.type));
85+
86+
// Combine the hashes
87+
return h1 ^ (h2 << 1) ^ (h3 << 2);
88+
}
89+
};
90+
91+
// Equality comparison for hash table
92+
struct KeyEqual {
93+
bool operator()(const Key& lhs, const Key& rhs) const {
94+
return lhs == rhs;
95+
}
96+
};
97+
6098
private:
61-
const boost::asio::ip::tcp::endpoint endpoint;
62-
const Connection::Type type;
99+
boost::asio::ip::tcp::endpoint endpoint;
100+
Connection::Type type;
63101
};
64102

65103
struct Entry {
@@ -400,8 +438,8 @@ class ConnectionPoolImpl
400438
#endif
401439
std::once_flag close_once_;
402440
RestClient& owner_;
403-
multimap<Key, Entry::ptr_t> idle_;
404-
multimap<Key, std::weak_ptr<Entry>> in_use_;
441+
unordered_multimap<Key, Entry::ptr_t, Key::KeyHash, Key::KeyEqual> idle_;
442+
unordered_multimap<Key, std::weak_ptr<Entry>, Key::KeyHash, Key::KeyEqual> in_use_;
405443
//std::queue<Entry> pending_;
406444
const Request::Properties::ptr_t properties_;
407445
ConnectionWrapper::release_callback_t on_release_;

0 commit comments

Comments
 (0)