diff --git a/common/expirecontainer.cpp b/common/expirecontainer.cpp index 4e9e3a0b..2b3b80a6 100644 --- a/common/expirecontainer.cpp +++ b/common/expirecontainer.cpp @@ -18,10 +18,12 @@ limitations under the License. #include ExpireContainerBase::ExpireContainerBase(uint64_t lifespan, - uint64_t timer_cycle) + uint64_t timer_cycle, + bool expire_if_possible) : _lifespan(lifespan), _timer(std::max(static_cast(1000), timer_cycle), - {this, &ExpireContainerBase::expire}, true, 8UL * 1024 * 1024) {} + {this, &ExpireContainerBase::expire}, true), + _expire_if_possible(expire_if_possible) {} auto ExpireContainerBase::insert(Item* item) -> std::pair { return _set.emplace(item); @@ -38,24 +40,31 @@ auto ExpireContainerBase::find(const Item& key_item) -> iterator { } void ExpireContainerBase::clear() { - for (auto x : ({ - SCOPED_LOCK(_lock); - _list.node = nullptr; - Set(std::move(_set)); - })) { - delete x; + Set tmp; + { + SCOPED_LOCK(_lock); + _list.node = nullptr; + tmp = std::move(_set); } + for (auto x : tmp) + delete x; } uint64_t ExpireContainerBase::expire() { - ({ + if (_lifespan > UINT64_MAX / 2) + return 0; + intrusive_list expired; + { SCOPED_LOCK(_lock); - _list.split_by_predicate([&](Item* x) { + auto tmp = _list.split_by_predicate([&](Item* x) { bool ret = x->_timeout.expiration() < photon::now; if (ret) _set.erase(x); return ret; }); - }).delete_all(); + expired = tmp; + tmp.node = nullptr; + } + expired.delete_all(); return 0; } @@ -79,7 +88,7 @@ auto ObjectCacheBase::ref_acquire(const Item& key_item, uint64_t failure_cooldown) -> Item* { Base::iterator holder; Item* item = nullptr; - expire(); + if (_expire_if_possible) expire(); do { SCOPED_LOCK(_lock); holder = Base::__find_prelock(key_item); @@ -115,7 +124,9 @@ auto ObjectCacheBase::ref_acquire(const Item& key_item, } int ObjectCacheBase::ref_release(ItemPtr item, bool recycle) { - DEFER(expire()); + DEFER({ + if (_expire_if_possible) expire(); + }); photon::semaphore sem; { SCOPED_LOCK(_lock); diff --git a/common/expirecontainer.h b/common/expirecontainer.h index 6453e3e3..1aa0126c 100644 --- a/common/expirecontainer.h +++ b/common/expirecontainer.h @@ -79,6 +79,7 @@ class ExpireContainerBase : public Object { intrusive_list _list; uint64_t _lifespan; photon::Timer _timer; + bool _expire_if_possible; photon::spinlock _lock; // protect _list/_set operations using ItemPtr = Item*; @@ -94,9 +95,6 @@ class ExpireContainerBase : public Object { using Set = std::unordered_set; Set _set; - ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle); - ~ExpireContainerBase() { clear(); } - using iterator = decltype(_set)::iterator; std::pair insert(Item* item); iterator begin() { return _set.begin(); } @@ -121,6 +119,11 @@ class ExpireContainerBase : public Object { } public: + explicit ExpireContainerBase(uint64_t lifespan) : ExpireContainerBase(lifespan, lifespan / 16, true) {} + ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle) : ExpireContainerBase(lifespan, timer_cycle, true) {} + ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle, bool expire_if_possible); + ~ExpireContainerBase() override { clear(); } + void clear(); uint64_t expire(); size_t size() { return _set.size(); } @@ -134,9 +137,7 @@ template class ExpireContainer : public ExpireContainerBase { public: using Base = ExpireContainerBase; - ExpireContainer(uint64_t expiration) : Base(expiration, expiration / 16) {} - ExpireContainer(uint64_t expiration, uint64_t timer_cycle) - : Base(expiration, timer_cycle) {} + using Base::Base; protected: using KeyedItem = typename Base::KeyedItem; @@ -198,7 +199,6 @@ class ExpireContainer : public ExpireContainerBase { // a set / list like structure // able to query whether an item not expired in it. - template class ExpireList : public ExpireContainer { public: @@ -367,6 +367,7 @@ template class __ObjectCache : public ObjectCacheBase { public: using Base = ObjectCacheBase; + using Base::Base; using Item = ItemType; using KeyedItem = Base::KeyedItem; using InterfaceKey = typename Item::InterfaceKey; @@ -374,10 +375,6 @@ class __ObjectCache : public ObjectCacheBase { using ValEntity = typename Item::ValEntity; using Borrow = typename Base::Borrow<__ObjectCache>; - __ObjectCache(uint64_t expiration) : Base(expiration, expiration / 16) {} - __ObjectCache(uint64_t expiration, uint64_t timer_cycle) - : Base(expiration, timer_cycle) {} - template ItemPtr ref_acquire(const InterfaceKey& key, const Constructor& ctor, uint64_t failure_cooldown = 0) { diff --git a/thread/timer.h b/thread/timer.h index d8e789b2..d0a7fe5f 100644 --- a/thread/timer.h +++ b/thread/timer.h @@ -30,7 +30,7 @@ namespace photon // 0 for default_timeout (given in the ctor) using Entry = Delegate; - // Create a timer object with `default_timedout` in usec, callback function `on_timer`, + // Create a timer object with `default_timeout` in usec, callback function `on_timer`, // and callback argument `arg`. The timer object is implemented as a special thread, so // it has a `stack_size`, and the `on_timer` is invoked within the thread's context. // The timer object is deleted automatically after it is finished. @@ -39,6 +39,7 @@ namespace photon { _on_timer = on_timer; _default_timeout = default_timeout; + _reset_timeout = -1UL; _repeating = repeating; _th = thread_create(&_stub, this, stack_size); thread_enable_join(_th);