1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License") override;
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <cstdint>
18 #include <limits>
19 #include <optional>
20 #include <type_traits>
21 #include <unordered_map>
22 
23 namespace gfxstream {
24 namespace magma {
25 
26 // A container with automatic monotonically increasing key values.
27 template <typename K, typename V, std::enable_if_t<std::is_integral_v<K>, bool> = true>
28 class MonotonicMap {
29    public:
MonotonicMap()30     MonotonicMap() {
31         static_assert(std::numeric_limits<K>::max() >= std::numeric_limits<int64_t>::max(),
32                       "Key type should be sufficiently large so as to not overflow.");
33     }
34 
35     // Creates a new object using the provided parameters with the constructor, and returns the new
36     // key associated with it.
37     template <typename... Params>
create(Params &&...params)38     K create(Params&&... params) {
39         assert(mNextKey < std::numeric_limits<K>::max());
40         auto key = mNextKey++;
41         auto [it, emplaced] = mMap.emplace(key, V(std::forward<Params>(params)...));
42         return key;
43     }
44 
45     // Returns a pointer to the object associated with the given key, or nullptr if the key is
46     // invalid. The pointer remains valid until the container is destroyed or the key is removed.
get(const K & key)47     V* get(const K& key) {
48         auto it = mMap.find(key);
49         if (it == mMap.end()) {
50             return nullptr;
51         }
52         return &it->second;
53     }
54 
55     // Destroys the object with the associated key and removes it from the map. Returns true iff the
56     // key was valid.
erase(const K & key)57     bool erase(const K& key) { return mMap.erase(key) > 0; }
58 
59    private:
60     K mNextKey = 1;
61     std::unordered_map<K, V> mMap;
62 };
63 
64 }  // namespace magma
65 }  // namespace gfxstream
66