1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #include <functional>
9 #include <memory>
10 #include <mutex>
11 #include <optional>
12 
13 #include <folly/container/EvictingCacheMap.h>
14 
15 namespace ABI49_0_0facebook {
16 namespace ABI49_0_0React {
17 
18 /*
19  * Simple thread-safe LRU cache.
20  */
21 template <typename KeyT, typename ValueT, int maxSize>
22 class SimpleThreadSafeCache {
23  public:
SimpleThreadSafeCache()24   SimpleThreadSafeCache() : map_{maxSize} {}
SimpleThreadSafeCache(unsigned long size)25   SimpleThreadSafeCache(unsigned long size) : map_{size} {}
26 
27   /*
28    * Returns a value from the map with a given key.
29    * If the value wasn't found in the cache, constructs the value using given
30    * generator function, stores it inside a cache and returns it.
31    * Can be called from any thread.
32    */
get(const KeyT & key,std::function<ValueT (const KeyT & key)> generator)33   ValueT get(const KeyT &key, std::function<ValueT(const KeyT &key)> generator)
34       const {
35     std::lock_guard<std::mutex> lock(mutex_);
36     auto iterator = map_.find(key);
37     if (iterator == map_.end()) {
38       auto value = generator(key);
39       map_.set(key, value);
40       return value;
41     }
42 
43     return iterator->second;
44   }
45 
46   /*
47    * Returns a value from the map with a given key.
48    * If the value wasn't found in the cache, returns empty optional.
49    * Can be called from any thread.
50    */
get(const KeyT & key)51   std::optional<ValueT> get(const KeyT &key) const {
52     std::lock_guard<std::mutex> lock(mutex_);
53     auto iterator = map_.find(key);
54     if (iterator == map_.end()) {
55       return {};
56     }
57 
58     return iterator->second;
59   }
60 
61   /*
62    * Sets a key-value pair in the LRU cache.
63    * Can be called from any thread.
64    */
set(const KeyT & key,const ValueT & value)65   void set(const KeyT &key, const ValueT &value) const {
66     std::lock_guard<std::mutex> lock(mutex_);
67     map_.set(std::move(key), std::move(value));
68   }
69 
70  private:
71   mutable folly::EvictingCacheMap<KeyT, ValueT> map_;
72   mutable std::mutex mutex_;
73 };
74 
75 } // namespace ABI49_0_0React
76 } // namespace ABI49_0_0facebook
77