Skip to content

Commit 1781306

Browse files
committed
Changed ConnectionPoolImpl to use std/boost::unordered_multimap to prevent reported runtime error under Windows. Closes #164
1 parent 31f2fa2 commit 1781306

File tree

2 files changed

+65
-18
lines changed

2 files changed

+65
-18
lines changed

CMakeLists.txt

+1-1
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

+64-17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323

2424
using namespace std;
2525

26+
#if __cplusplus < 201703L
27+
# include <boost/unordered_map.hpp>
28+
#endif
29+
30+
2631
namespace restc_cpp {
2732

2833
class ConnectionPoolImpl
@@ -31,35 +36,73 @@ class ConnectionPoolImpl
3136
public:
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

Comments
 (0)