diff options
author | James M Snell <jasnell@gmail.com> | 2020-08-03 21:36:49 +0300 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2020-08-10 17:52:03 +0300 |
commit | 6d1f0aed52b890e4f4bfa2281894df4d423cf1c6 (patch) | |
tree | 99c75e6e4ca8ff4f5fef67454dd20aae5d32036b /src/node_sockaddr-inl.h | |
parent | 6b0b33cd4ca647865457be2199c31b16bab14648 (diff) |
src: add SocketAddressLRU Utility
Adds a LRU cache for information associated with a SocketAddress.
PR-URL: https://github.com/nodejs/node/pull/34618
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src/node_sockaddr-inl.h')
-rw-r--r-- | src/node_sockaddr-inl.h | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/node_sockaddr-inl.h b/src/node_sockaddr-inl.h index a9d0ed061a1..c8b985aedda 100644 --- a/src/node_sockaddr-inl.h +++ b/src/node_sockaddr-inl.h @@ -7,6 +7,7 @@ #include "node_internals.h" #include "node_sockaddr.h" #include "util-inl.h" +#include "memory_tracker-inl.h" #include <string> @@ -164,6 +165,72 @@ bool SocketAddress::operator==(const SocketAddress& other) const { bool SocketAddress::operator!=(const SocketAddress& other) const { return !(*this == other); } + +template <typename T> +SocketAddressLRU<T>::SocketAddressLRU( + size_t max_size) + : max_size_(max_size) {} + +template <typename T> +typename T::Type* SocketAddressLRU<T>::Peek( + const SocketAddress& address) const { + auto it = map_.find(address); + return it == std::end(map_) ? nullptr : &it->second->second; +} + +template <typename T> +void SocketAddressLRU<T>::CheckExpired() { + auto it = list_.rbegin(); + while (it != list_.rend()) { + if (T::CheckExpired(it->first, it->second)) { + map_.erase(it->first); + list_.pop_back(); + it = list_.rbegin(); + continue; + } else { + break; + } + } +} + +template <typename T> +void SocketAddressLRU<T>::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackFieldWithSize("list", size() * sizeof(Pair)); +} + +// If an item already exists for the given address, bump up it's +// position in the LRU list and return it. If the item does not +// exist, create it. If an item is created, check the size of the +// cache and adjust if necessary. Whether the item exists or not, +// purge expired items. +template <typename T> +typename T::Type* SocketAddressLRU<T>::Upsert( + const SocketAddress& address) { + + auto on_exit = OnScopeLeave([&]() { CheckExpired(); }); + + auto it = map_.find(address); + if (it != std::end(map_)) { + list_.splice(list_.begin(), list_, it->second); + T::Touch(it->first, &it->second->second); + return &it->second->second; + } + + list_.push_front(Pair(address, { })); + map_[address] = list_.begin(); + T::Touch(list_.begin()->first, &list_.begin()->second); + + // Drop the last item in the list if we are + // over the size limit... + if (map_.size() > max_size_) { + auto last = list_.end(); + map_.erase((--last)->first); + list_.pop_back(); + } + + return &map_[address]->second; +} + } // namespace node #endif // NODE_WANT_INTERNALS |