#ifndef CONCURRENT_ID_MAP_HPP #define CONCURRENT_ID_MAP_HPP #include #include #include #include namespace osrm { namespace util { /** * This is a special purpose map for caching incrementing IDs */ template > struct ConcurrentIDMap { static_assert(std::is_unsigned::value, "Only unsigned integer types are supported."); using UpgradableMutex = boost::interprocess::interprocess_upgradable_mutex; using ScopedReaderLock = boost::interprocess::sharable_lock; using ScopedWriterLock = boost::interprocess::scoped_lock; std::unordered_map data; mutable UpgradableMutex mutex; ConcurrentIDMap() = default; ConcurrentIDMap(ConcurrentIDMap &&other) { if (this != &other) { ScopedWriterLock other_lock{other.mutex}; ScopedWriterLock lock{mutex}; data = std::move(other.data); } } ConcurrentIDMap &operator=(ConcurrentIDMap &&other) { if (this != &other) { ScopedWriterLock other_lock{other.mutex}; ScopedWriterLock lock{mutex}; data = std::move(other.data); } return *this; } const ValueType ConcurrentFindOrAdd(const KeyType &key) { { ScopedReaderLock sentry{mutex}; const auto result = data.find(key); if (result != data.end()) { return result->second; } } { ScopedWriterLock sentry{mutex}; const auto result = data.find(key); if (result != data.end()) { return result->second; } const auto id = static_cast(data.size()); data[key] = id; return id; } } }; } // util } // osrm #endif // CONCURRENT_ID_MAP_HPP