10namespace opcua::detail {
22template <
typename T,
typename =
void>
23struct IsStaleable : std::false_type {};
26struct IsStaleable<T, std::void_t<decltype(std::declval<T>().stale)>>
27 : std::is_same<decltype(std::declval<T>().stale), bool> {};
41template <
typename Key,
typename Item>
45 Item* operator[](Key key) {
47 auto lock = acquireLock();
48 auto& item = map_[key];
49 if (item ==
nullptr) {
50 item = std::make_unique<Item>();
56 Item* insert(Key key, std::unique_ptr<Item>&& item) {
58 auto lock = acquireLock();
59 return map_.insert_or_assign(key, std::move(item)).first->second.get();
62 size_t erase(Key key) {
63 auto lock = acquireLock();
64 return map_.erase(key);
68 const size_t count = map_.size();
69 if constexpr (IsStaleable<Item>::value) {
70 auto lock = acquireLock();
71 for (
auto it = map_.begin(); it != map_.end();) {
72 if (it->second->stale) {
79 return count - map_.size();
82 bool contains(Key key)
const {
83 auto lock = acquireLock();
84 return map_.count(key) > 0;
87 const Item* find(Key key)
const {
88 auto lock = acquireLock();
89 auto it = map_.find(key);
90 if (it != map_.end()) {
91 return it->second.get();
97 void iterate(F&& func)
const {
98 auto lock = acquireLock();
99 for (
const auto& pair : map_) {
100 std::invoke(func, pair);
105 [[nodiscard]]
auto acquireLock()
const {
106 return std::scoped_lock(mutex_);
109 std::map<Key, std::unique_ptr<Item>> map_;
110 mutable std::mutex mutex_;