Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Expmap takes additional template parameter for clock type. #1636

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions ecal/core/src/util/ecal_expmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,14 @@ namespace eCAL
**/
template<class Key,
class T,
class clock_type = std::chrono::steady_clock,
class Compare = std::less<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class CExpMap
{
public:
using clock_type = std::chrono::steady_clock;

// Key access history, most recent at back
using key_tracker_type = std::list<std::pair<clock_type::time_point, Key>>;
using key_tracker_type = std::list<std::pair<typename clock_type::time_point, Key>>;

// Key to value and key history iterator
using key_to_value_type = std::map<Key, std::pair<T, typename key_tracker_type::iterator>>;
Expand Down Expand Up @@ -147,12 +146,12 @@ namespace eCAL

// Constructor specifies the timeout of the map
CExpMap() : _timeout(std::chrono::milliseconds(5000)) {};
explicit CExpMap(clock_type::duration t) : _timeout(t) {};
explicit CExpMap(typename clock_type::duration t) : _timeout(t) {};

/**
* @brief set expiration time
**/
void set_expiration(clock_type::duration t) { _timeout = t; };
void set_expiration(typename clock_type::duration t) { _timeout = t; };

// Iterators:
iterator begin() noexcept
Expand Down Expand Up @@ -261,7 +260,7 @@ namespace eCAL
{
// Assert method is never called when cache is empty
//assert(!_key_tracker.empty());
clock_type::time_point eviction_limit = get_curr_time() - _timeout;
typename clock_type::time_point eviction_limit = get_curr_time() - _timeout;

auto it(_key_tracker.begin());

Expand Down Expand Up @@ -328,7 +327,7 @@ namespace eCAL
return ret;
}

clock_type::time_point get_curr_time()
typename clock_type::time_point get_curr_time()
{
return clock_type::now();
}
Expand All @@ -340,7 +339,7 @@ namespace eCAL
key_to_value_type _key_to_value;

// Timeout of map
clock_type::duration _timeout;
typename clock_type::duration _timeout;
};
}
}
75 changes: 53 additions & 22 deletions ecal/tests/cpp/expmap_test/src/expmap_test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* ========================= eCAL LICENSE =================================
*
* Copyright (C) 2016 - 2019 Continental Corporation
* Copyright (C) 2016 - 2024 Continental Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -27,10 +27,41 @@

#include <gtest/gtest.h>

class TestingClock {
public:
// Define the required types for TrivialClock
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<TestingClock>;
static const bool is_steady = false;

// Function to get the current time
static time_point now() noexcept {
return time_point(current_time);
}

// Function to manually set the current time
static void set_time(const time_point& tp) {
current_time = tp.time_since_epoch();
}

// Function to manually increment the current time by a given duration
static void increment_time(const duration& d) {
current_time += d;
}

private:
static duration current_time;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'current_time' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

  static duration current_time;
                  ^

};

// Initialize the static member
TestingClock::duration TestingClock::current_time{ 0 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'current_time' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

TestingClock::duration TestingClock::current_time{ 0 };
                                     ^


TEST(core_cpp_core, ExpMap_SetGet)
{
// create the map with 2500 ms expiration
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));

// set "A"
expmap["A"] = 1;
Expand All @@ -43,7 +74,7 @@ TEST(core_cpp_core, ExpMap_SetGet)
EXPECT_EQ(1, expmap.size());

// sleep
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));

// access and reset timer
EXPECT_EQ(1, expmap["A"]);
Expand All @@ -54,41 +85,41 @@ TEST(core_cpp_core, ExpMap_SetGet)
EXPECT_EQ(1, expmap.size());

// sleep
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));

// check size
//content = expmap.clone();
expmap.remove_deprecated();
EXPECT_EQ(1, expmap.size());

// sleep
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));

// check size
//content = expmap.clone();
expmap.remove_deprecated();
EXPECT_EQ(0, expmap.size());

expmap["A"] = 1;
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));
expmap["B"] = 2;
expmap["C"] = 3;
expmap.remove_deprecated();
EXPECT_EQ(3, expmap.size());
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));
expmap["B"] = 4;
expmap.remove_deprecated();
EXPECT_EQ(2, expmap.size());
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));
expmap.remove_deprecated();
EXPECT_EQ(1, expmap.size());
// sleep
std::this_thread::sleep_for(std::chrono::milliseconds(150));
TestingClock::increment_time(std::chrono::milliseconds(150));
}

TEST(core_cpp_core, ExpMap_Insert)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
auto ret = expmap.insert(std::make_pair("A", 1));

auto key = (*ret.first).first;
Expand All @@ -100,15 +131,15 @@ TEST(core_cpp_core, ExpMap_Insert)

EXPECT_EQ(i, 1);

std::this_thread::sleep_for(std::chrono::milliseconds(300));
TestingClock::increment_time(std::chrono::milliseconds(300));
expmap.remove_deprecated();
EXPECT_EQ(0, expmap.size());
}

// This tests uses find to find an element
TEST(core_cpp_core, ExpMap_Find)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));

auto it = expmap.find("A");
EXPECT_EQ(expmap.end(), it);
Expand All @@ -119,15 +150,15 @@ TEST(core_cpp_core, ExpMap_Find)
int i = (*it).second;
EXPECT_EQ(i, 1);

std::this_thread::sleep_for(std::chrono::milliseconds(300));
TestingClock::increment_time(std::chrono::milliseconds(300));
expmap.remove_deprecated();
EXPECT_EQ(0, expmap.size());
}

// This test assures that find can be called on a const CExpMap and returns an CExpMap::const_iterator
TEST(core_cpp_core, ExpMap_FindConst)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));

auto it = expmap.find("A");
EXPECT_EQ(expmap.end(), it);
Expand All @@ -137,19 +168,19 @@ TEST(core_cpp_core, ExpMap_FindConst)
const auto& const_ref_exmap = expmap;
auto const_it = const_ref_exmap.find("A");
// assert that we are actually getting a const_iterator here!
static_assert(std::is_same<decltype(const_it), eCAL::Util::CExpMap<std::string, int>::const_iterator>::value, "We're not being returned a const_iterator from find.");
static_assert(std::is_same<decltype(const_it), eCAL::Util::CExpMap<std::string, int, TestingClock>::const_iterator>::value, "We're not being returned a const_iterator from find.");
int i = (*const_it).second;
EXPECT_EQ(i, 1);

std::this_thread::sleep_for(std::chrono::milliseconds(300));
TestingClock::increment_time(std::chrono::milliseconds(300));
expmap.remove_deprecated();
EXPECT_EQ(0, expmap.size());
}

TEST(core_cpp_core, ExpMap_Iterate)
{
// create the map with 2500 ms expiration
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
expmap["A"] = 1;

std::string key;
Expand All @@ -165,7 +196,7 @@ TEST(core_cpp_core, ExpMap_Iterate)
EXPECT_EQ(1, value);
}

void ConstRefIterate(const eCAL::Util::CExpMap<std::string, int>& map)
void ConstRefIterate(const eCAL::Util::CExpMap<std::string, int, TestingClock>& map)
{
std::string key;
int value;
Expand All @@ -183,31 +214,31 @@ void ConstRefIterate(const eCAL::Util::CExpMap<std::string, int>& map)
TEST(core_cpp_core, ExpMap_ConstExpMapIterate)
{
// create the map with 2500 ms expiration
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
expmap["A"] = 1;

ConstRefIterate(expmap);
}

TEST(core_cpp_core, ExpMap_Empty)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
EXPECT_EQ(true, expmap.empty());
expmap["A"] = 1;
EXPECT_EQ(false, expmap.empty());
}

TEST(core_cpp_core, ExpMap_Size)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
EXPECT_EQ(0, expmap.size());
expmap["A"] = 1;
EXPECT_EQ(1, expmap.size());
}

TEST(core_cpp_core, ExpMap_Remove)
{
eCAL::Util::CExpMap<std::string, int> expmap(std::chrono::milliseconds(200));
eCAL::Util::CExpMap<std::string, int, TestingClock> expmap(std::chrono::milliseconds(200));
expmap["A"] = 1;
EXPECT_EQ(1, expmap.size());
EXPECT_TRUE(expmap.erase("A"));
Expand Down
Loading