8
8
#pragma once
9
9
10
10
#include < concepts>
11
+ #include < list>
11
12
#include < mutex>
12
- #include < optional>
13
- #include < type_traits>
14
-
15
- #include < folly/container/EvictingCacheMap.h>
13
+ #include < unordered_map>
16
14
17
15
namespace facebook ::react {
18
16
@@ -26,8 +24,8 @@ concept CacheGeneratorFunction = std::invocable<GeneratorT> &&
26
24
template <typename KeyT, typename ValueT, int maxSize>
27
25
class SimpleThreadSafeCache {
28
26
public:
29
- SimpleThreadSafeCache () : map_{ maxSize} {}
30
- SimpleThreadSafeCache (unsigned long size) : map_ {size} {}
27
+ SimpleThreadSafeCache () : maxSize_( maxSize) {}
28
+ SimpleThreadSafeCache (unsigned long size) : maxSize_ {size} {}
31
29
32
30
/*
33
31
* Returns a value from the map with a given key.
@@ -38,14 +36,23 @@ class SimpleThreadSafeCache {
38
36
ValueT get (const KeyT& key, CacheGeneratorFunction<ValueT> auto generator)
39
37
const {
40
38
std::lock_guard<std::mutex> lock (mutex_);
41
- auto iterator = map_. find (key);
42
- if (iterator = = map_.end ()) {
43
- auto value = generator ();
44
- map_. set (key, value );
45
- return value ;
39
+
40
+ if (auto it = map_. find (key); it ! = map_.end ()) {
41
+ // Move accessed item to front of list
42
+ list_. splice (list_. begin (), list_, it-> second );
43
+ return it-> second -> second ;
46
44
}
47
45
48
- return iterator->second ;
46
+ auto value = generator ();
47
+ // Add new value to front of list and map
48
+ list_.emplace_front (key, value);
49
+ map_[key] = list_.begin ();
50
+ if (list_.size () > maxSize_) {
51
+ // Evict least recently used item (back of list)
52
+ map_.erase (list_.back ().first );
53
+ list_.pop_back ();
54
+ }
55
+ return value;
49
56
}
50
57
51
58
/*
@@ -55,26 +62,23 @@ class SimpleThreadSafeCache {
55
62
*/
56
63
std::optional<ValueT> get (const KeyT& key) const {
57
64
std::lock_guard<std::mutex> lock (mutex_);
58
- auto iterator = map_.find (key);
59
- if (iterator == map_.end ()) {
60
- return {};
65
+
66
+ if (auto it = map_.find (key); it != map_.end ()) {
67
+ // Move accessed item to front of list
68
+ list_.splice (list_.begin (), list_, it->second );
69
+ return it->second ->second ;
61
70
}
62
71
63
- return iterator->second ;
64
- }
65
-
66
- /*
67
- * Sets a key-value pair in the LRU cache.
68
- * Can be called from any thread.
69
- */
70
- void set (const KeyT& key, const ValueT& value) const {
71
- std::lock_guard<std::mutex> lock (mutex_);
72
- map_.set (std::move (key), std::move (value));
72
+ return ValueT{};
73
73
}
74
74
75
75
private:
76
- mutable folly::EvictingCacheMap<KeyT, ValueT> map_;
76
+ using iterator = typename std::list<std::pair<KeyT, ValueT>>::iterator;
77
+
78
+ size_t maxSize_;
77
79
mutable std::mutex mutex_;
80
+ mutable std::list<std::pair<KeyT, ValueT>> list_;
81
+ mutable std::unordered_map<KeyT, iterator> map_;
78
82
};
79
83
80
84
} // namespace facebook::react
0 commit comments