]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | #include "TTLCache.h" |
2 | ||
3 | #include <chrono> | |
4 | #include <functional> | |
5 | #include <string> | |
6 | ||
7 | #include "PyUtil.h" | |
8 | ||
9 | template <class Key, class Value> | |
10 | void TTLCacheBase<Key, Value>::insert(Key key, Value value) { | |
11 | auto now = std::chrono::steady_clock::now(); | |
12 | ||
13 | if (!ttl) return; | |
14 | int16_t random_ttl_offset = | |
15 | ttl * ttl_spread_ratio * (2l * rand() / float(RAND_MAX) - 1); | |
16 | // in order not to have spikes of misses we increase or decrease by 25% of | |
17 | // the ttl | |
18 | int16_t spreaded_ttl = ttl + random_ttl_offset; | |
19 | auto expiration_date = now + std::chrono::seconds(spreaded_ttl); | |
20 | cache::insert(key, {value, expiration_date}); | |
21 | } | |
22 | ||
23 | template <class Key, class Value> Value TTLCacheBase<Key, Value>::get(Key key) { | |
24 | if (!exists(key)) { | |
25 | throw_key_not_found(key); | |
26 | } | |
27 | if (expired(key)) { | |
28 | erase(key); | |
29 | throw_key_not_found(key); | |
30 | } | |
31 | Value value = {get_value(key)}; | |
32 | return value; | |
33 | } | |
34 | ||
35 | template <class Key> PyObject* TTLCache<Key, PyObject*>::get(Key key) { | |
36 | if (!this->exists(key)) { | |
37 | this->throw_key_not_found(key); | |
38 | } | |
39 | if (this->expired(key)) { | |
40 | this->erase(key); | |
41 | this->throw_key_not_found(key); | |
42 | } | |
43 | PyObject* cached_value = this->get_value(key); | |
44 | Py_INCREF(cached_value); | |
45 | return cached_value; | |
46 | } | |
47 | ||
48 | template <class Key, class Value> | |
49 | void TTLCacheBase<Key, Value>::erase(Key key) { | |
50 | cache::erase(key); | |
51 | } | |
52 | ||
53 | template <class Key> void TTLCache<Key, PyObject*>::erase(Key key) { | |
54 | Py_DECREF(this->get_value(key, false)); | |
55 | ttl_base::erase(key); | |
56 | } | |
57 | ||
58 | template <class Key, class Value> | |
59 | bool TTLCacheBase<Key, Value>::expired(Key key) { | |
60 | ttl_time_point expiration_date = get_value_time_point(key); | |
61 | auto now = std::chrono::steady_clock::now(); | |
62 | if (now >= expiration_date) { | |
63 | return true; | |
64 | } else { | |
65 | return false; | |
66 | } | |
67 | } | |
68 | ||
69 | template <class Key, class Value> void TTLCacheBase<Key, Value>::clear() { | |
70 | cache::clear(); | |
71 | } | |
72 | ||
73 | template <class Key, class Value> | |
74 | Value TTLCacheBase<Key, Value>::get_value(Key key, bool count_hit) { | |
75 | value_type stored_value = cache::get(key, count_hit); | |
76 | Value value = std::get<0>(stored_value); | |
77 | return value; | |
78 | } | |
79 | ||
80 | template <class Key, class Value> | |
81 | ttl_time_point TTLCacheBase<Key, Value>::get_value_time_point(Key key) { | |
82 | value_type stored_value = cache::get(key, false); | |
83 | ttl_time_point tp = std::get<1>(stored_value); | |
84 | return tp; | |
85 | } | |
86 | ||
87 | template <class Key, class Value> | |
88 | void TTLCacheBase<Key, Value>::set_ttl(uint16_t ttl) { | |
89 | this->ttl = ttl; | |
90 | } | |
91 | ||
92 | template <class Key, class Value> | |
93 | bool TTLCacheBase<Key, Value>::exists(Key key) { | |
94 | return cache::exists(key); | |
95 | } | |
96 | ||
97 | template <class Key, class Value> | |
98 | void TTLCacheBase<Key, Value>::throw_key_not_found(Key key) { | |
99 | cache::throw_key_not_found(key); | |
100 | } |