fix expire cache
All checks were successful
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m30s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m50s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 2m15s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m22s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m24s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 3m6s
All checks were successful
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m30s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m50s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 2m15s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m22s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m24s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 3m6s
This commit is contained in:
parent
0bafdc98c7
commit
794535e9a1
@ -201,8 +201,10 @@ if(SLED_BUILD_TESTS)
|
|||||||
sled_add_test(NAME sled_ioc_test SRCS src/sled/ioc/ioc_test.cc)
|
sled_add_test(NAME sled_ioc_test SRCS src/sled/ioc/ioc_test.cc)
|
||||||
sled_add_test(NAME sled_inja_test SRCS src/sled/nonstd/inja_test.cc)
|
sled_add_test(NAME sled_inja_test SRCS src/sled/nonstd/inja_test.cc)
|
||||||
sled_add_test(NAME sled_fsm_test SRCS src/sled/nonstd/fsm_test.cc)
|
sled_add_test(NAME sled_fsm_test SRCS src/sled/nonstd/fsm_test.cc)
|
||||||
sled_add_test(NAME sled_cache_test SRCS src/sled/cache/lru_cache_test.cc
|
sled_add_test(NAME sled_timestamp_test SRCS src/sled/units/timestamp_test.cc)
|
||||||
src/sled/cache/fifo_cache_test.cc)
|
sled_add_test(
|
||||||
|
NAME sled_cache_test SRCS src/sled/cache/lru_cache_test.cc
|
||||||
|
src/sled/cache/fifo_cache_test.cc src/sled/cache/expire_cache_test.cc)
|
||||||
endif(SLED_BUILD_TESTS)
|
endif(SLED_BUILD_TESTS)
|
||||||
|
|
||||||
if(SLED_BUILD_FUZZ)
|
if(SLED_BUILD_FUZZ)
|
||||||
|
5
src/sled/cache/expire_cache.h
vendored
5
src/sled/cache/expire_cache.h
vendored
@ -9,6 +9,11 @@ namespace sled {
|
|||||||
template<typename TKey, typename TValue>
|
template<typename TKey, typename TValue>
|
||||||
class ExpireCache : public AbstractCache<TKey, TValue, ExpireCachePolicy<TKey>> {
|
class ExpireCache : public AbstractCache<TKey, TValue, ExpireCachePolicy<TKey>> {
|
||||||
public:
|
public:
|
||||||
|
ExpireCache(const TimeDelta &expire_time)
|
||||||
|
{
|
||||||
|
this->policy_.insert(std::make_shared<ExpireCachePolicy<TKey>>(expire_time));
|
||||||
|
}
|
||||||
|
|
||||||
~ExpireCache() override = default;
|
~ExpireCache() override = default;
|
||||||
};
|
};
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
18
src/sled/cache/expire_cache_test.cc
vendored
Normal file
18
src/sled/cache/expire_cache_test.cc
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <sled/cache/expire_cache.h>
|
||||||
|
#include <sled/system/thread.h>
|
||||||
|
|
||||||
|
TEST_SUITE("Expire Cache")
|
||||||
|
{
|
||||||
|
TEST_CASE("Remove Expired Key")
|
||||||
|
{
|
||||||
|
sled::ExpireCache<int, int> expire_cache(sled::TimeDelta::Millis(25));
|
||||||
|
expire_cache.Add(1, 1);
|
||||||
|
REQUIRE(expire_cache.Has(1));
|
||||||
|
CHECK_EQ(*expire_cache.Get(1), 1);
|
||||||
|
|
||||||
|
sled::Thread::SleepMs(30);
|
||||||
|
CHECK_FALSE(expire_cache.Has(1));
|
||||||
|
CHECK(expire_cache.empty());
|
||||||
|
CHECK_EQ(expire_cache.Get(1), nullptr);
|
||||||
|
}
|
||||||
|
}
|
18
src/sled/cache/policy/expire_cache_policy.h
vendored
18
src/sled/cache/policy/expire_cache_policy.h
vendored
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "abstract_cache_policy.h"
|
#include "abstract_cache_policy.h"
|
||||||
#include "sled/time_utils.h"
|
|
||||||
#include "sled/units/timestamp.h"
|
#include "sled/units/timestamp.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@ -12,12 +11,14 @@ namespace sled {
|
|||||||
template<typename TKey>
|
template<typename TKey>
|
||||||
class ExpireCachePolicy : public AbstractCachePolicy<TKey> {
|
class ExpireCachePolicy : public AbstractCachePolicy<TKey> {
|
||||||
public:
|
public:
|
||||||
|
ExpireCachePolicy(const TimeDelta &expire_time) : expire_time_(expire_time) {}
|
||||||
|
|
||||||
~ExpireCachePolicy() override = default;
|
~ExpireCachePolicy() override = default;
|
||||||
|
|
||||||
void OnAdd(const TKey &key) override
|
void OnAdd(const TKey &key) override
|
||||||
{
|
{
|
||||||
Timestamp now = Timestamp::Nanos(TimeNanos());
|
Timestamp cur_expire_time = Timestamp::Now() + expire_time_;
|
||||||
auto iter = key_index_.insert(std::make_pair(now, key));
|
auto iter = key_index_.insert(std::make_pair(cur_expire_time, key));
|
||||||
keys_[key] = iter;
|
keys_[key] = iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,8 +45,7 @@ public:
|
|||||||
void OnReplace(std::set<TKey> &elems_to_remove) override
|
void OnReplace(std::set<TKey> &elems_to_remove) override
|
||||||
{
|
{
|
||||||
auto iter = key_index_.begin();
|
auto iter = key_index_.begin();
|
||||||
Timestamp now = Timestamp::Nanos(TimeNanos());
|
while (iter != key_index_.end() && iter->first.IsExpired()) {
|
||||||
while (iter != key_index_.end() && iter->first < now) {
|
|
||||||
elems_to_remove.insert(iter->second);
|
elems_to_remove.insert(iter->second);
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
@ -54,15 +54,11 @@ public:
|
|||||||
bool IsValid(const TKey &key) override
|
bool IsValid(const TKey &key) override
|
||||||
{
|
{
|
||||||
auto iter = keys_.find(key);
|
auto iter = keys_.find(key);
|
||||||
if (iter != keys_.end()) {
|
return iter != keys_.end() && !iter->second->first.IsExpired();
|
||||||
return iter->second->first + expire_time_ > Timestamp::Nanos(TimeNanos());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimeDelta expire_time_;
|
const TimeDelta expire_time_;
|
||||||
std::multimap<Timestamp, TKey> key_index_;
|
std::multimap<Timestamp, TKey> key_index_;
|
||||||
std::map<TKey, typename std::multimap<Timestamp, TKey>::iterator> keys_;
|
std::map<TKey, typename std::multimap<Timestamp, TKey>::iterator> keys_;
|
||||||
};
|
};
|
||||||
|
13
src/sled/cache/policy/fifo_cache_policy.h
vendored
13
src/sled/cache/policy/fifo_cache_policy.h
vendored
@ -41,9 +41,18 @@ public:
|
|||||||
BaseClass::OnClear();
|
BaseClass::OnClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnReplace(std::set<TKey> &key) override
|
void OnReplace(std::set<TKey> &elems_to_remove) override
|
||||||
{
|
{
|
||||||
// do nothing
|
BaseClass::OnReplace(elems_to_remove);
|
||||||
|
|
||||||
|
if (keys_.size() <= size_) { return; }
|
||||||
|
std::size_t diff = keys_.size() - size_;
|
||||||
|
std::size_t index = 0;
|
||||||
|
auto iter = keys_.begin();
|
||||||
|
while (index++ < diff) {
|
||||||
|
elems_to_remove.insert(*iter);
|
||||||
|
if (iter != keys_.end()) { ++iter; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid(const TKey &key) override { return BaseClass::IsValid(key); }
|
bool IsValid(const TKey &key) override { return BaseClass::IsValid(key); }
|
||||||
|
@ -27,18 +27,25 @@ public:
|
|||||||
static constexpr TimeDelta Seconds(T value)
|
static constexpr TimeDelta Seconds(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromFraction(1000000, value);
|
return FromFraction(1000000000, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr TimeDelta Millis(T value)
|
static constexpr TimeDelta Millis(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromFraction(1000, value);
|
return FromFraction(1000000, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr TimeDelta Micros(T value)
|
static constexpr TimeDelta Micros(T value)
|
||||||
|
{
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
|
return FromFraction(1000, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static constexpr TimeDelta Nanos(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromValue(value);
|
return FromValue(value);
|
||||||
@ -47,7 +54,7 @@ public:
|
|||||||
template<typename Clock, typename Duration>
|
template<typename Clock, typename Duration>
|
||||||
inline TimeDelta(const std::chrono::duration<Clock, Duration> &duration)
|
inline TimeDelta(const std::chrono::duration<Clock, Duration> &duration)
|
||||||
{
|
{
|
||||||
*this = FromValue(std::chrono::duration_cast<std::chrono::microseconds>(duration).count());
|
*this = FromValue(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeDelta() = delete;
|
TimeDelta() = delete;
|
||||||
@ -55,32 +62,34 @@ public:
|
|||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T seconds() const
|
constexpr T seconds() const
|
||||||
{
|
{
|
||||||
return ToFraction<1000000, T>();
|
return ToFraction<1000000000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T ms() const
|
constexpr T ms() const
|
||||||
{
|
{
|
||||||
return ToFraction<1000, T>();
|
return ToFraction<1000000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T us() const
|
constexpr T us() const
|
||||||
{
|
{
|
||||||
return ToValue<T>();
|
return ToFraction<1000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T ns() const
|
constexpr T ns() const
|
||||||
{
|
{
|
||||||
return ToMultiple<1000, T>();
|
return ToValue<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int64_t seconds_or(int64_t fallback_value) const { return ToFractionOr<1000000>(fallback_value); }
|
constexpr int64_t seconds_or(int64_t fallback_value) const { return ToFractionOr<1000000000>(fallback_value); }
|
||||||
|
|
||||||
constexpr int64_t ms_or(int64_t fallback_value) const { return ToFractionOr<1000>(fallback_value); }
|
constexpr int64_t ms_or(int64_t fallback_value) const { return ToFractionOr<1000000>(fallback_value); }
|
||||||
|
|
||||||
constexpr int64_t us_or(int64_t fallback_value) const { return ToValueOr(fallback_value); }
|
constexpr int64_t us_or(int64_t fallback_value) const { return ToFractionOr<1000>(fallback_value); }
|
||||||
|
|
||||||
|
constexpr int64_t ns_or(int64_t fallback_value) const { return ToValueOr(fallback_value); }
|
||||||
|
|
||||||
constexpr TimeDelta Abs() const { return us() < 0 ? TimeDelta::Micros(-us()) : *this; }
|
constexpr TimeDelta Abs() const { return us() < 0 ? TimeDelta::Micros(-us()) : *this; }
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef SLED_UNITS_TIMESTAMP_H
|
#ifndef SLED_UNITS_TIMESTAMP_H
|
||||||
#define SLED_UNITS_TIMESTAMP_H
|
#define SLED_UNITS_TIMESTAMP_H
|
||||||
|
#include "sled/time_utils.h"
|
||||||
#include "sled/units/time_delta.h"
|
#include "sled/units/time_delta.h"
|
||||||
#include "sled/units/unit_base.h"
|
#include "sled/units/unit_base.h"
|
||||||
|
|
||||||
@ -14,65 +15,71 @@ namespace sled {
|
|||||||
|
|
||||||
class Timestamp final : public detail::UnitBase<Timestamp> {
|
class Timestamp final : public detail::UnitBase<Timestamp> {
|
||||||
public:
|
public:
|
||||||
|
static Timestamp Now() { return Timestamp::Nanos(TimeNanos()); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr Timestamp Seconds(T value)
|
static constexpr Timestamp Seconds(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromFraction(1000000, value);
|
return FromFraction(1000000000, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr Timestamp Millis(T value)
|
static constexpr Timestamp Millis(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromFraction(1000, value);
|
return FromFraction(1000000, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr Timestamp Micros(T value)
|
static constexpr Timestamp Micros(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromValue(value);
|
return FromFraction(1000, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr Timestamp Nanos(T value)
|
static constexpr Timestamp Nanos(T value)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic<T>::value, "");
|
static_assert(std::is_arithmetic<T>::value, "");
|
||||||
return FromValue(value * 1000LL);
|
return FromValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp() = delete;
|
Timestamp() = delete;
|
||||||
|
|
||||||
|
bool IsExpired() const { return *this < Now(); }
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T seconds() const
|
constexpr T seconds() const
|
||||||
{
|
{
|
||||||
return ToFraction<1000000, T>();
|
return ToFraction<1000000000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T ms() const
|
constexpr T ms() const
|
||||||
{
|
{
|
||||||
return ToFraction<1000, T>();
|
return ToFraction<1000000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T us() const
|
constexpr T us() const
|
||||||
{
|
{
|
||||||
return ToValue<T>();
|
return ToFraction<1000, T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = int64_t>
|
template<typename T = int64_t>
|
||||||
constexpr T ns() const
|
constexpr T ns() const
|
||||||
{
|
{
|
||||||
return ToMultiple<1000, T>();
|
return ToValue<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int64_t seconds_or(int64_t fallback_value) const { return ToFractionOr<1000000>(fallback_value); }
|
constexpr int64_t seconds_or(int64_t fallback_value) const { return ToFractionOr<1000000000>(fallback_value); }
|
||||||
|
|
||||||
constexpr int64_t ms_or(int64_t fallback_value) const { return ToFractionOr<1000>(fallback_value); }
|
constexpr int64_t ms_or(int64_t fallback_value) const { return ToFractionOr<1000000>(fallback_value); }
|
||||||
|
|
||||||
constexpr int64_t us_or(int64_t fallback_value) const { return ToValueOr(fallback_value); }
|
constexpr int64_t us_or(int64_t fallback_value) const { return ToFractionOr<1000>(fallback_value); }
|
||||||
|
|
||||||
|
constexpr int64_t ns_or(int64_t fallback_value) const { return ToValueOr(fallback_value); }
|
||||||
|
|
||||||
Timestamp operator+(const TimeDelta delta) const
|
Timestamp operator+(const TimeDelta delta) const
|
||||||
{
|
{
|
||||||
@ -81,7 +88,7 @@ public:
|
|||||||
} else if (IsMinusInfinity() || delta.IsMinusInfinity()) {
|
} else if (IsMinusInfinity() || delta.IsMinusInfinity()) {
|
||||||
return MinusInfinity();
|
return MinusInfinity();
|
||||||
}
|
}
|
||||||
return Timestamp::Micros(us() - delta.us());
|
return Timestamp::Nanos(ns() + delta.ns());
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp operator-(const TimeDelta delta) const
|
Timestamp operator-(const TimeDelta delta) const
|
||||||
@ -91,7 +98,7 @@ public:
|
|||||||
} else if (IsMinusInfinity() || delta.IsPlusInfinity()) {
|
} else if (IsMinusInfinity() || delta.IsPlusInfinity()) {
|
||||||
return MinusInfinity();
|
return MinusInfinity();
|
||||||
}
|
}
|
||||||
return Timestamp::Micros(us() - delta.us());
|
return Timestamp::Nanos(ns() - delta.ns());
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeDelta operator-(const Timestamp other) const
|
TimeDelta operator-(const Timestamp other) const
|
||||||
|
21
src/sled/units/timestamp_test.cc
Normal file
21
src/sled/units/timestamp_test.cc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <sled/units/timestamp.h>
|
||||||
|
|
||||||
|
TEST_SUITE("Timestamp")
|
||||||
|
{
|
||||||
|
TEST_CASE("ToString")
|
||||||
|
{
|
||||||
|
CHECK_EQ(sled::ToString(sled::Timestamp::PlusInfinity()), "+inf ms");
|
||||||
|
CHECK_EQ(sled::ToString(sled::Timestamp::MinusInfinity()), "-inf ms");
|
||||||
|
CHECK_EQ(sled::ToString(sled::Timestamp::Micros(1)), "1 us");
|
||||||
|
CHECK_EQ(sled::ToString(sled::Timestamp::Millis(1)), "1 ms");
|
||||||
|
CHECK_EQ(sled::ToString(sled::Timestamp::Seconds(1)), "1 s");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("IsExpired")
|
||||||
|
{
|
||||||
|
auto passed = sled::Timestamp::Now() - sled::TimeDelta::Millis(1);
|
||||||
|
CHECK(passed.IsExpired());
|
||||||
|
auto future = sled::Timestamp::Now() + sled::TimeDelta::Millis(1);
|
||||||
|
CHECK_FALSE(future.IsExpired());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user