#pragma once #include #include #include #include #include #include namespace VUtils { template struct SafeMap { explicit SafeMap(size_t maxSize = -1UL) : m_maxSize(maxSize), m_end(false) {}; bool add(const T &t, S &x); bool add(T &&t, S &&x); void remove(T t); void clear(); bool has(T t); S &get(T t); int size(); private: std::unordered_map m_map{}; std::mutex m_mtx{}; std::condition_variable m_cvFull{}; const size_t m_maxSize{}; std::atomic m_end{}; }; template bool SafeMap::add(const T &t, S &x) { std::unique_lock lck(m_mtx); while (m_map.size() == m_maxSize && !m_end) { return false; } assert(!m_end); m_map.emplace(t, std::move(x)); return true; } template bool SafeMap::add(T &&t, S &&x) { std::unique_lock lck(m_mtx); while (m_map.size() == m_maxSize && !m_end) return false; assert(!m_end); m_map.push(std::move(t)); return true; } template void SafeMap::clear() { std::unique_lock lck(m_mtx); std::unordered_map empty; std::swap(m_map, empty); m_cvFull.notify_all(); } template void SafeMap::remove(T t) { std::unique_lock lck(m_mtx); if (m_map.empty() || m_end) return; if (m_map.contains(t)) { m_map.erase(t); } m_cvFull.notify_one(); } template int SafeMap::size() { return m_map.size(); } template bool SafeMap::has(T t) { std::unique_lock lck(m_mtx); return m_map.contains(t); } template S &SafeMap::get(T t) { std::unique_lock lck(m_mtx); return m_map[t]; } }