1616
1717#pragma once
1818
19+ #include < atomic>
1920#include < chrono>
2021#include < cstdint>
2122#include < functional>
@@ -63,6 +64,8 @@ class GenericLruCache {
6364 // / Configuration options for the cache.
6465 struct Options {
6566 // / Maximum total weight of all entries. Entries are evicted (LRU) when exceeded.
67+ // / Used only as the initial value for the cache's runtime-mutable max weight;
68+ // / after construction, use GetMaxWeight()/SetMaxWeight() to read or update it.
6669 int64_t max_weight = INT64_MAX ;
6770
6871 // / Time in milliseconds after last access before an entry expires.
@@ -77,7 +80,8 @@ class GenericLruCache {
7780 RemovalCallback removal_callback = nullptr ;
7881 };
7982
80- explicit GenericLruCache (Options options) : options_(std::move(options)) {}
83+ explicit GenericLruCache (Options options)
84+ : options_(std::move(options)), max_weight_(options_.max_weight) {}
8185
8286 // / Look up a key in the cache. On hit, promotes the entry to the front (most recently
8387 // / used) and updates its access time. Returns std::nullopt on miss or if the entry
@@ -101,7 +105,7 @@ class GenericLruCache {
101105 // Cache miss: load via supplier outside the lock
102106 PAIMON_ASSIGN_OR_RAISE (V value, supplier (key));
103107 int64_t weight = ComputeWeight (key, value);
104- if (weight > options_. max_weight ) {
108+ if (weight > max_weight_. load (std::memory_order_relaxed) ) {
105109 return value;
106110 }
107111
@@ -122,10 +126,11 @@ class GenericLruCache {
122126 // / @return Status::Invalid if the entry's weight exceeds max_weight, Status::OK otherwise.
123127 Status Put (const K& key, V value) {
124128 int64_t weight = ComputeWeight (key, value);
125- if (weight > options_.max_weight ) {
129+ int64_t max_weight = max_weight_.load (std::memory_order_relaxed);
130+ if (weight > max_weight) {
126131 return Status::Invalid (
127132 fmt::format (" Entry weight {} exceeds cache max weight {}, entry will not be cached" ,
128- weight, options_. max_weight ));
133+ weight, max_weight));
129134 }
130135
131136 std::unique_lock<std::shared_mutex> lock (mutex_);
@@ -176,7 +181,22 @@ class GenericLruCache {
176181
177182 // / @return The maximum weight configured for this cache.
178183 int64_t GetMaxWeight () const {
179- return options_.max_weight ;
184+ return max_weight_.load (std::memory_order_relaxed);
185+ }
186+
187+ // / Update the maximum total weight at runtime. The new limit is published with
188+ // / release semantics so subsequent insertions on other threads observe it without
189+ // / needing the cache lock. After updating, this method also acquires the write
190+ // / lock and runs EvictIfNeeded() so that:
191+ // / 1. expired entries are reaped opportunistically;
192+ // / 2. when the new limit is smaller than current_weight_, entries are evicted
193+ // / down to the new limit immediately rather than being held until the next
194+ // / insertion (relevant when the cache is being shrunk or disabled and no
195+ // / further inserts are expected).
196+ void SetMaxWeight (int64_t new_max_weight) {
197+ max_weight_.store (new_max_weight, std::memory_order_relaxed);
198+ std::unique_lock<std::shared_mutex> lock (mutex_);
199+ EvictIfNeeded ();
180200 }
181201
182202 private:
@@ -267,7 +287,8 @@ class GenericLruCache {
267287 // / Evict expired entries from the tail, then evict by weight if still over capacity.
268288 void EvictIfNeeded () {
269289 EvictExpired ();
270- while (current_weight_ > options_.max_weight && !lru_list_.empty ()) {
290+ while (current_weight_ > max_weight_.load (std::memory_order_relaxed) &&
291+ !lru_list_.empty ()) {
271292 RemoveEntry (std::prev (lru_list_.end ()), RemovalCause::SIZE );
272293 }
273294 }
@@ -317,6 +338,10 @@ class GenericLruCache {
317338 }
318339
319340 Options options_;
341+ // / Runtime-mutable maximum total weight. Read on the hot path without holding
342+ // / `mutex_` (e.g. in Get/Put before locking, and inside EvictIfNeeded under
343+ // / the write lock). Writes go through SetMaxWeight() which uses relaxed atomics.
344+ std::atomic<int64_t > max_weight_;
320345 int64_t current_weight_ = 0 ;
321346 EntryList lru_list_;
322347 EntryMap lru_map_;
0 commit comments