source/UniquePointerConcurrentMap.h (52 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <ConcurrentContainers.h> namespace marianatrench { /** * A thread-safe map from `Key` to `std::unique_pointer<const Value>`. * `ConcurrentMap` can only return by value. `UniquePointerConcurrentMap` can * be used instead to avoid copying on lookup. */ template <typename Key, typename Value> class UniquePointerConcurrentMap final { private: using Map = ConcurrentMap<Key, const Value*>; public: // C++ container concept member types using iterator = typename Map::const_iterator; using const_iterator = iterator; using key_type = Key; using mapped_type = const Value*; using value_type = std::pair<const key_type, mapped_type>; using difference_type = std::ptrdiff_t; using size_type = std::size_t; using const_reference = const value_type&; using const_pointer = const value_type*; public: UniquePointerConcurrentMap() = default; UniquePointerConcurrentMap(const UniquePointerConcurrentMap&) = delete; UniquePointerConcurrentMap(UniquePointerConcurrentMap&&) = delete; UniquePointerConcurrentMap& operator=(const UniquePointerConcurrentMap&) = delete; UniquePointerConcurrentMap& operator=(UniquePointerConcurrentMap&&) = delete; ~UniquePointerConcurrentMap() { // ConcurrentMap can only return by value, hence we need to store a raw // pointer and use delete here. for (const auto& entry : map_) { delete entry.second; } } const Value* at(const Key& key) const { return map_.at(key); } const Value* get(const Key& key, const Value* default_value) const { return map_.get(key, default_value); } bool emplace(const Key& key, std::unique_ptr<Value> value) { bool inserted = map_.emplace(key, value.get()); if (inserted) { value.release(); } return inserted; } /** * Iterating on the container while calling `emplace` concurrently is unsafe. */ iterator begin() const { return map_.cbegin(); } iterator end() const { return map_.cend(); } private: Map map_; }; } // namespace marianatrench