92 float tickInterval = TICK_INTERVAL,
93 size_t wheelsNum = WHEELS_NUM,
94 size_t bucketsNumPerWheel = BUCKET_NUM_PER_WHEEL,
95 std::function<
void(
const T1 &)> fnOnInsert =
nullptr,
96 std::function<
void(
const T1 &)> fnOnErase =
nullptr)
98 tickInterval_(tickInterval),
99 wheelsNumber_(wheelsNum),
100 bucketsNumPerWheel_(bucketsNumPerWheel),
101 ctrlBlockPtr_(
std::make_shared<ControlBlock>()),
102 fnOnInsert_(fnOnInsert),
103 fnOnErase_(fnOnErase)
105 wheels_.resize(wheelsNumber_);
106 for (
size_t i = 0; i < wheelsNumber_; ++i)
108 wheels_[i].resize(bucketsNumPerWheel_);
110 if (tickInterval_ > 0 && wheelsNumber_ > 0 && bucketsNumPerWheel_ > 0)
112 timerId_ = loop_->runEvery(
113 tickInterval_, [
this, ctrlBlockPtr = ctrlBlockPtr_]() {
114 std::lock_guard<std::mutex> lock(ctrlBlockPtr->mtx);
115 if (ctrlBlockPtr->destructed)
118 size_t t = ++ticksCounter_;
120 for (
size_t i = 0; i < wheelsNumber_; ++i)
126 std::lock_guard<std::mutex> lock(bucketMutex_);
129 wheels_[i].front().swap(tmp);
130 wheels_[i].pop_front();
131 wheels_[i].push_back(CallbackBucket());
134 pow = pow * bucketsNumPerWheel_;
137 loop_->runOnQuit([ctrlBlockPtr = ctrlBlockPtr_] {
138 std::lock_guard<std::mutex> lock(ctrlBlockPtr->mtx);
139 ctrlBlockPtr->loopEnded =
true;
150 std::lock_guard<std::mutex> lock(ctrlBlockPtr_->mtx);
151 ctrlBlockPtr_->destructed =
true;
153 if (!ctrlBlockPtr_->loopEnded)
155 loop_->invalidateTimer(timerId_);
157 for (
auto iter = wheels_.rbegin(); iter != wheels_.rend(); ++iter)
161 LOG_TRACE <<
"CacheMap destruct!";
166 MapValue(
const T2 &value,
168 std::function<
void()> &&callback)
171 timeoutCallback_(std::move(callback))
175 MapValue(T2 &&value,
size_t timeout, std::function<
void()> &&callback)
176 : value_(std::move(value)),
178 timeoutCallback_(std::move(callback))
182 MapValue(T2 &&value,
size_t timeout)
183 : value_(std::move(value)), timeout_(timeout)
187 MapValue(
const T2 &value,
size_t timeout)
188 : value_(value), timeout_(timeout)
192 MapValue(T2 &&value) : value_(std::move(value))
196 MapValue(
const T2 &value) : value_(value)
200 MapValue() =
default;
203 std::function<void()> timeoutCallback_;
204 WeakCallbackEntryPtr weakEntryPtr_;
220 std::function<
void()> timeoutCallback = std::function<
void()>())
224 MapValue v{std::move(value), timeout, std::move(timeoutCallback)};
225 std::lock_guard<std::mutex> lock(mtx_);
226 map_.insert(std::make_pair(key, std::move(v)));
227 eraseAfter(timeout, key);
232 std::lock_guard<std::mutex> lock(mtx_);
233 map_.insert(std::make_pair(key, std::move(v)));
252 std::function<
void()> timeoutCallback = std::function<
void()>())
256 MapValue v{value, timeout, std::move(timeoutCallback)};
257 std::lock_guard<std::mutex> lock(mtx_);
258 map_.insert(std::make_pair(key, std::move(v)));
259 eraseAfter(timeout, key);
264 std::lock_guard<std::mutex> lock(mtx_);
265 map_.insert(std::make_pair(key, std::move(v)));
283 std::lock_guard<std::mutex> lock(mtx_);
284 auto iter = map_.find(key);
285 if (iter != map_.end())
287 timeout = iter->second.timeout_;
289 eraseAfter(timeout, key);
290 return iter->second.value_;
311 template <
typename Callable>
312 void modify(
const T1 &key, Callable &&handler,
size_t timeout = 0)
315 std::lock_guard<std::mutex> lock(mtx_);
316 auto iter = map_.find(key);
317 if (iter != map_.end())
319 timeout = iter->second.timeout_;
320 handler(iter->second.value_);
322 eraseAfter(timeout, key);
328 map_.insert(std::make_pair(key, std::move(v)));
331 eraseAfter(timeout, key);
344 std::lock_guard<std::mutex> lock(mtx_);
345 auto iter = map_.find(key);
346 if (iter != map_.end())
348 timeout = iter->second.timeout_;
353 eraseAfter(timeout, key);
367 std::lock_guard<std::mutex> lock(mtx_);
368 auto iter = map_.find(key);
369 if (iter != map_.end())
371 timeout = iter->second.timeout_;
373 value = iter->second.value_;
377 eraseAfter(timeout, key);
391 std::lock_guard<std::mutex> lock(mtx_);
417 void runAfter(
size_t delay, std::function<
void()> &&task)
419 std::lock_guard<std::mutex> lock(bucketMutex_);
420 insertEntry(delay, std::make_shared<CallbackEntry>(std::move(task)));
423 void runAfter(
size_t delay,
const std::function<
void()> &task)
425 std::lock_guard<std::mutex> lock(bucketMutex_);
426 insertEntry(delay, std::make_shared<CallbackEntry>(task));
441 ControlBlock() : destructed(false), loopEnded(false)
450 std::unordered_map<T1, MapValue> map_;
452 std::vector<CallbackBucketQueue> wheels_;
454 std::atomic<size_t> ticksCounter_{0};
457 std::mutex bucketMutex_;
458 trantor::TimerId timerId_;
459 trantor::EventLoop *loop_;
462 size_t wheelsNumber_;
463 size_t bucketsNumPerWheel_;
464 std::shared_ptr<ControlBlock> ctrlBlockPtr_;
465 std::function<void(
const T1 &)> fnOnInsert_;
466 std::function<void(
const T1 &)> fnOnErase_;
468 bool noWheels_{
false};
470 void insertEntry(
size_t delay, CallbackEntryPtr entryPtr)
475 delay =
static_cast<size_t>(delay / tickInterval_ + 1);
476 size_t t = ticksCounter_;
477 for (
size_t i = 0; i < wheelsNumber_; ++i)
479 if (delay <= bucketsNumPerWheel_)
481 wheels_[i][delay - 1].insert(entryPtr);
484 if (i < (wheelsNumber_ - 1))
486 entryPtr = std::make_shared<CallbackEntry>(
487 [
this, delay, i, t, entryPtr]() {
490 std::lock_guard<std::mutex> lock(bucketMutex_);
491 wheels_[i][(delay + (t % bucketsNumPerWheel_) - 1) %
500 wheels_[i][bucketsNumPerWheel_ - 1].insert(entryPtr);
503 (delay + (t % bucketsNumPerWheel_) - 1) / bucketsNumPerWheel_;
504 t = t / bucketsNumPerWheel_;
508 void eraseAfter(
size_t delay,
const T1 &key)
512 assert(map_.find(key) != map_.end());
514 CallbackEntryPtr entryPtr;
516 if (map_.find(key) != map_.end())
518 entryPtr = map_[key].weakEntryPtr_.lock();
523 std::lock_guard<std::mutex> lock(bucketMutex_);
524 insertEntry(delay, entryPtr);
528 std::function<void()> cb = [
this, key]() {
530 std::function<void()> timeoutCallback;
532 std::lock_guard<std::mutex> lock(mtx_);
533 auto iter = map_.find(key);
534 if (iter != map_.end())
536 auto &value = iter->second;
537 auto entryPtr = value.weakEntryPtr_.lock();
539 if (value.timeout_ > 0 && !entryPtr)
542 timeoutCallback = std::move(value.timeoutCallback_);
547 if (erased && fnOnErase_)
549 if (erased && timeoutCallback)
552 entryPtr = std::make_shared<CallbackEntry>(std::move(cb));
553 map_[key].weakEntryPtr_ = entryPtr;
555 std::lock_guard<std::mutex> lock(bucketMutex_);
556 insertEntry(delay, entryPtr);
CacheMap(trantor::EventLoop *loop, float tickInterval=TICK_INTERVAL, size_t wheelsNum=WHEELS_NUM, size_t bucketsNumPerWheel=BUCKET_NUM_PER_WHEEL, std::function< void(const T1 &)> fnOnInsert=nullptr, std::function< void(const T1 &)> fnOnErase=nullptr)
constructor
Definition CacheMap.h:91
void insert(const T1 &key, T2 &&value, size_t timeout=0, std::function< void()> timeoutCallback=std::function< void()>())
Insert a key-value pair into the cache.
Definition CacheMap.h:217
void insert(const T1 &key, const T2 &value, size_t timeout=0, std::function< void()> timeoutCallback=std::function< void()>())
Insert a key-value pair into the cache.
Definition CacheMap.h:249
void modify(const T1 &key, Callable &&handler, size_t timeout=0)
Modify or visit the data identified by the key parameter.
Definition CacheMap.h:312