9namespace opcua::detail {
21template <
typename T,
typename =
void>
22struct IsStaleable : std::false_type {};
25struct IsStaleable<T, std::void_t<decltype(std::declval<T>().stale)>>
26 : std::is_same<decltype(std::declval<T>().stale), bool> {};
34template <
typename Key,
typename Item>
38 Item* operator[](Key key) {
40 auto lock = acquireLock();
41 auto& item = map_[key];
42 if (item ==
nullptr) {
43 item = std::make_unique<Item>();
49 Item* insert(Key key, std::unique_ptr<Item>&& item) {
51 auto lock = acquireLock();
52 return map_.insert_or_assign(key, std::move(item)).first->second.get();
55 size_t erase(Key key) {
56 auto lock = acquireLock();
57 return map_.erase(key);
61 const size_t count = map_.size();
62 if constexpr (IsStaleable<Item>::value) {
63 auto lock = acquireLock();
64 for (
auto it = map_.begin(); it != map_.end();) {
65 if (it->second->stale) {
72 return count - map_.size();
75 bool contains(Key key)
const {
76 auto lock = acquireLock();
77 return map_.count(key) > 0;
80 const Item* find(Key key)
const {
81 auto lock = acquireLock();
82 auto it = map_.find(key);
83 if (it != map_.end()) {
84 return it->second.get();
90 void iterate(F&& func)
const {
91 auto lock = acquireLock();
92 for (
const auto& pair : map_) {
93 std::invoke(func, pair);
98 [[nodiscard]]
auto acquireLock()
const {
99 return std::scoped_lock(mutex_);
102 std::map<Key, std::unique_ptr<Item>> map_;
103 mutable std::mutex mutex_;