42#ifndef _DWMIPV4PREFIXMAP_HH_
43#define _DWMIPV4PREFIXMAP_HH_
48#include <shared_mutex>
49#include <unordered_map>
60 struct OurIpv4PrefixHash
64 return pfx.NetworkRaw();
71 template <
typename T,
typename Hash = OurIpv4PrefixHash>
78 using MapType = std::unordered_map<Ipv4Prefix,T,Hash>;
84 : _mtx(), _map(), _lengthCounters()
86 _map.max_load_factor(.15);
92 void Add(
const Ipv4Prefix & pfx,
const T & value)
94 std::unique_lock lck(_mtx);
95 return Add(lck, pfx, value);
101 void Add(std::unique_lock<std::shared_mutex> & lck,
102 const Ipv4Prefix & pfx,
const T & value)
104 assert((lck.mutex() == &_mtx) && lck.owns_lock());
105 if (_map.insert_or_assign(pfx, value).second) {
106 _lengthCounters[pfx.MaskLength()]++;
114 bool Find(
const Ipv4Prefix & pfx, T & value)
const
116 std::shared_lock lck(_mtx);
117 return Find(lck, pfx, value);
123 bool Find(std::shared_lock<std::shared_mutex> & lck,
124 const Ipv4Prefix & pfx, T & value)
const
126 assert((lck.mutex() == &_mtx) && lck.owns_lock());
127 return FindNoLock(pfx, value);
133 bool Find(std::unique_lock<std::shared_mutex> & lck,
134 const Ipv4Prefix & pfx, T & value)
136 assert((lck.mutex() == &_mtx) && lck.owns_lock());
137 return FindNoLock(pfx, value);
143 bool FindLongest(
const Ipv4Address & addr,
144 std::pair<Ipv4Prefix,T> & value)
const
146 std::shared_lock lck(_mtx);
147 return FindLongest(lck, addr, value);
153 bool FindLongest(std::shared_lock<std::shared_mutex> & lck,
154 const Ipv4Address & addr,
155 std::pair<Ipv4Prefix,T> & value)
const
157 assert((lck.mutex() == &_mtx) && lck.owns_lock());
158 return FindLongestNoLock(addr, value);
164 bool FindLongest(std::unique_lock<std::shared_mutex> & lck,
165 const Ipv4Address & addr,
166 std::pair<Ipv4Prefix,T> & value)
168 assert((lck.mutex() == &_mtx) && lck.owns_lock());
169 return FindLongestNoLock(addr, value);
175 bool FindMatches(
const Ipv4Address & addr,
176 std::vector<std::pair<Ipv4Prefix,T>> & values)
const
178 std::shared_lock lck(_mtx);
179 return FindMatches(lck, addr, values);
185 bool FindMatches(std::shared_lock<std::shared_mutex> & lck,
186 const Ipv4Address & addr,
187 std::vector<std::pair<Ipv4Prefix,T>> & values)
const
189 assert((lck.mutex() == &_mtx) && lck.owns_lock());
190 return FindMatchesNoLock(addr, values);
196 bool FindMatches(std::unique_lock<std::shared_mutex> & lck,
197 const Ipv4Address & addr,
198 std::vector<std::pair<Ipv4Prefix,T>> & values)
200 assert((lck.mutex() == &_mtx) && lck.owns_lock());
201 return FindMatchesNoLock(addr, values);
207 bool Remove(
const Ipv4Prefix & pfx)
209 std::unique_lock lck(_mtx);
210 return Remove(lck, pfx);
216 bool Remove(std::unique_lock<std::shared_mutex> & lck,
217 const Ipv4Prefix & pfx)
220 auto it = _map.find(pfx);
221 if (it != _map.end()) {
223 auto lit = _lengthCounters.find(pfx.MaskLength());
225 if (0 == lit->second) {
226 _lengthCounters.erase(lit);
236 void Rehash(
typename MapType::size_type count)
244 std::shared_lock<std::shared_mutex> SharedLock()
const
246 return std::shared_lock(_mtx);
252 std::unique_lock<std::shared_mutex> UniqueLock()
254 return std::unique_lock(_mtx);
258 mutable std::shared_mutex _mtx;
260 std::map<uint8_t,uint64_t> _lengthCounters;
265 bool FindNoLock(
const Ipv4Prefix & pfx, T & value)
const
268 auto it = _map.find(pfx);
269 if (it != _map.end()) {
279 bool FindLongestNoLock(
const Ipv4Address & addr,
280 std::pair<Ipv4Prefix,T> & value)
const
283 Ipv4Prefix pfx(addr, 32);
284 for (
auto lit = _lengthCounters.rbegin();
285 lit != _lengthCounters.rend(); ++lit) {
286 pfx.MaskLength(lit->first);
287 auto it = _map.find(pfx);
288 if (it != _map.end()) {
290 value.second = it->second;
302 FindMatchesNoLock(
const Ipv4Address & addr,
303 std::vector<std::pair<Ipv4Prefix,T>> & values)
const
306 std::pair<Ipv4Prefix,T> value;
307 for (
auto lit = _lengthCounters.rbegin();
308 lit != _lengthCounters.rend(); ++lit) {
309 Ipv4Prefix pfx(addr, lit->first);
310 auto it = _map.find(pfx);
311 if (it != _map.end()) {
313 value.second = it->second;
314 values.push_back(value);
317 return (! values.empty());
Dwm::Ipv4Prefix class definition.
This class encapsulates an IPv4 address and netmask.
Definition DwmIpv4Prefix.hh:59