mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Work in progress
test_intrusive_timer_one_shot not working yet
This commit is contained in:
parent
d04cc5c296
commit
78bdd671fa
@ -85,6 +85,7 @@ namespace etl
|
||||
|
||||
if (!timer_.is_registered(this))
|
||||
{
|
||||
timer_.set_id(get_next_id());
|
||||
register_list.insert(timer_);
|
||||
timer_.set_owner(this);
|
||||
++timer_count;
|
||||
@ -102,10 +103,12 @@ namespace etl
|
||||
//*******************************************
|
||||
bool unregister_timer(etl::timer_node& timer_) ETL_NOEXCEPT
|
||||
{
|
||||
lock_policy.lock();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (timer_.is_registered(this))
|
||||
{
|
||||
lock_policy.lock();
|
||||
|
||||
if (timer_.is_active())
|
||||
{
|
||||
active_list.remove(&timer_);
|
||||
@ -113,16 +116,14 @@ namespace etl
|
||||
|
||||
register_list.remove(&timer_);
|
||||
|
||||
lock_policy.unlock();
|
||||
|
||||
--timer_count;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
result = true;
|
||||
}
|
||||
|
||||
lock_policy.unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
@ -162,6 +163,8 @@ namespace etl
|
||||
//*******************************************
|
||||
bool tick(uint32_t count)
|
||||
{
|
||||
bool was_processed = false;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
if (!lock_policy.is_locked())
|
||||
@ -202,35 +205,36 @@ namespace etl
|
||||
// Subtract any remainder from the next due timeout.
|
||||
active_list.first()->delta -= count;
|
||||
}
|
||||
|
||||
lock_policy.unlock();
|
||||
|
||||
// Invoke all of the expired timers.
|
||||
invoke_expired_timers();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
lock_policy.unlock();
|
||||
|
||||
was_processed = true;
|
||||
|
||||
// Invoke all of the expired timers.
|
||||
invoke_expired_timers();
|
||||
}
|
||||
|
||||
return false;
|
||||
return was_processed;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Starts a timer.
|
||||
//*******************************************
|
||||
bool start(etl::timer_node* timer_, bool immediate_ = false) ETL_NOEXCEPT
|
||||
bool start(etl::timer_node& timer_, bool immediate_ = false) ETL_NOEXCEPT
|
||||
{
|
||||
bool is_started = false;
|
||||
|
||||
lock_policy.lock();
|
||||
|
||||
etl::timer_node* timer = register_list.find(timer_);
|
||||
|
||||
if (timer != register_list.end())
|
||||
if (timer_.is_registered(this))
|
||||
{
|
||||
active_list.insert(timer);
|
||||
is_started = true;
|
||||
if (!timer_.is_active())
|
||||
{
|
||||
active_list.insert(timer_);
|
||||
is_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
lock_policy.unlock();
|
||||
@ -238,7 +242,7 @@ namespace etl
|
||||
if (is_started && immediate_)
|
||||
{
|
||||
// Trigger the timer immediately.
|
||||
timer->invoke(timer->get_config());
|
||||
timer_.invoke(timer_.get_config());
|
||||
}
|
||||
|
||||
return is_started;
|
||||
|
||||
@ -41,6 +41,13 @@ SOFTWARE.
|
||||
// Definitions common to intrusive timers.
|
||||
//*****************************************************************************
|
||||
|
||||
#if defined(ETL_IN_UNIT_TEST)
|
||||
namespace
|
||||
{
|
||||
class etl_unit_test_intrusive_timer;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_timer
|
||||
@ -147,6 +154,10 @@ namespace etl
|
||||
|
||||
friend class intrusive_timer;
|
||||
|
||||
#if defined(ETL_IN_UNIT_TEST)
|
||||
friend class etl_unit_test_intrusive_timer;
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
@ -326,16 +337,16 @@ namespace etl
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A timer node that invokes a callback delegate.
|
||||
/// A timer node that invokes a callback delegate type.
|
||||
//***************************************************************************
|
||||
template <typename TCallback>
|
||||
struct callback_timer_node : public timer_node
|
||||
struct timer_callback_node : public timer_node
|
||||
{
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
callback_timer_node(TCallback callback_) ETL_NOEXCEPT
|
||||
: timer_node()
|
||||
timer_callback_node(TCallback callback_, const etl::timer_config& config_) ETL_NOEXCEPT
|
||||
: timer_node(config_)
|
||||
, callback(callback_)
|
||||
{
|
||||
}
|
||||
@ -355,13 +366,13 @@ namespace etl
|
||||
/// A timer node that invokes a message callback.
|
||||
//***************************************************************************
|
||||
template <typename TMessage>
|
||||
struct message_timer_node : public timer_node
|
||||
struct timer_message_node : public timer_node
|
||||
{
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
message_timer_node(etl::imessage_router& router_, TMessage message_) ETL_NOEXCEPT
|
||||
: timer_node()
|
||||
timer_message_node(const etl::timer_config& config_, etl::imessage_router& router_, TMessage message_) ETL_NOEXCEPT
|
||||
: timer_node(config_)
|
||||
, router(&router_)
|
||||
, message(message_)
|
||||
{
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
#include "Config.h"
|
||||
#include "TestResults.h"
|
||||
#include "MemoryOutStream.h"
|
||||
#include<iomanip>
|
||||
#include<iomanip>
|
||||
|
||||
namespace UnitTest
|
||||
namespace UnitTest
|
||||
{
|
||||
template <typename T>
|
||||
typename std::enable_if<!std::is_pointer<T>::value, std::string>::type
|
||||
@ -178,7 +178,7 @@ namespace UnitTest
|
||||
if (!(expected == actual))
|
||||
{
|
||||
UnitTest::MemoryOutStream stream;
|
||||
stream << "Expected "
|
||||
stream << "Expected "
|
||||
<< DisplayValue(expected) << " but was " << DisplayValue(actual);
|
||||
|
||||
results.OnTestFailure(details, stream.GetText());
|
||||
@ -205,7 +205,7 @@ namespace UnitTest
|
||||
if (!(expected == actual))
|
||||
{
|
||||
UnitTest::MemoryOutStream stream;
|
||||
stream << std::hex << std::uppercase << std::setfill('0')
|
||||
stream << std::hex << std::uppercase << std::setfill('0')
|
||||
<< "Expected 0x" << std::setw(2 * sizeof(Expected)) << (static_cast<typename std::make_unsigned<Expected>::type>(expected) & ~(typename std::make_unsigned<Expected>::type(0)))
|
||||
<< " but was 0x" << std::setw(2 * sizeof(Actual)) << (static_cast<typename std::make_unsigned<Actual>::type>(actual) & ~(typename std::make_unsigned<Actual>::type(0)));
|
||||
|
||||
@ -219,7 +219,7 @@ namespace UnitTest
|
||||
if (expected == actual)
|
||||
{
|
||||
UnitTest::MemoryOutStream stream;
|
||||
stream << "Expected not equal, but both values are" << actual;
|
||||
stream << "Expected not equal, but both values are " << actual;
|
||||
|
||||
results.OnTestFailure(details, stream.GetText());
|
||||
}
|
||||
@ -231,7 +231,7 @@ namespace UnitTest
|
||||
if (expected == actual)
|
||||
{
|
||||
UnitTest::MemoryOutStream stream;
|
||||
stream << std::hex << std::uppercase << std::setfill('0') << std::setw(2 * sizeof(Actual))
|
||||
stream << std::hex << std::uppercase << std::setfill('0') << std::setw(2 * sizeof(Actual))
|
||||
<< "Expected not equal, but both values are " << (actual & ~(typename std::make_unsigned<Actual>::type(0)));
|
||||
|
||||
results.OnTestFailure(details, stream.GetText());
|
||||
|
||||
@ -81,6 +81,9 @@ namespace
|
||||
|
||||
TimerInsertRemoveTest timerInsertRemoveTest;
|
||||
|
||||
//***************************************************************************
|
||||
/// A lock policy that counts the number of times it is locked and unlocked.
|
||||
/// The lock count should always be 0 or 1.
|
||||
//***************************************************************************
|
||||
class LockPolicy : public etl::timer_lock_policy
|
||||
{
|
||||
@ -93,16 +96,26 @@ namespace
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
~LockPolicy()
|
||||
{
|
||||
assert(count == 0);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void lock() ETL_NOEXCEPT override
|
||||
{
|
||||
++count;
|
||||
|
||||
assert(count == 1);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void unlock() ETL_NOEXCEPT override
|
||||
{
|
||||
--count;
|
||||
|
||||
assert(count == 0);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
@ -122,6 +135,94 @@ namespace
|
||||
int count;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
using CallbackDelegate = etl::delegate<void(const etl::timer_config&)>;
|
||||
using CallbackTimer = etl::timer_callback_node<CallbackDelegate>;
|
||||
|
||||
//*************************************************************************
|
||||
bool global_callback_called = false;
|
||||
const etl::timer_config* global_config;
|
||||
|
||||
static void global_callback(const etl::timer_config& config)
|
||||
{
|
||||
global_callback_called = true;
|
||||
global_config = &config;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
|
||||
Object()
|
||||
: member_callback_called(false)
|
||||
, member_config(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
void member(const etl::timer_config& config)
|
||||
{
|
||||
member_callback_called = true;
|
||||
member_config = &config;
|
||||
}
|
||||
|
||||
bool member_callback_called = false;
|
||||
const etl::timer_config* member_config;
|
||||
};
|
||||
|
||||
static Object object;
|
||||
|
||||
//*************************************************************************
|
||||
struct CallbackMessage : public etl::message<1>
|
||||
{
|
||||
CallbackMessage(int value_)
|
||||
: value(value_)
|
||||
, config(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
void set_timer_config(const etl::timer_config& config_)
|
||||
{
|
||||
config = &config_;
|
||||
}
|
||||
|
||||
int value;
|
||||
const etl::timer_config* config;
|
||||
};
|
||||
|
||||
class MessageProcessor : public etl::message_router<MessageProcessor, CallbackMessage>
|
||||
{
|
||||
public:
|
||||
|
||||
MessageProcessor()
|
||||
: etl::message_router<MessageProcessor, CallbackMessage>()
|
||||
, message_callback_called(false)
|
||||
, message_config(ETL_NULLPTR)
|
||||
, value(0)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void on_receive(const CallbackMessage& msg)
|
||||
{
|
||||
message_callback_called = true;
|
||||
message_config = msg.config;
|
||||
value = msg.value;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void on_receive_unknown(const etl::imessage& msg) {}
|
||||
|
||||
bool message_callback_called;
|
||||
const etl::timer_config* message_config;
|
||||
int value;
|
||||
};
|
||||
|
||||
using MessageTimer = etl::timer_message_node<CallbackMessage>;
|
||||
|
||||
MessageProcessor message_processor;
|
||||
CallbackMessage callback_message(42);
|
||||
|
||||
SUITE(test_intrusive_timer)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -219,49 +320,77 @@ namespace
|
||||
CHECK_EQUAL(0U, lock_policy.get_count());
|
||||
}
|
||||
|
||||
////*************************************************************************
|
||||
// TEST(test_intrusive_timer_one_shot)
|
||||
//{
|
||||
// LockPolicy lock_policy;
|
||||
//*************************************************************************
|
||||
TEST(test_intrusive_timer_one_shot)
|
||||
{
|
||||
LockPolicy lock_policy;
|
||||
|
||||
// etl::intrusive_timer timer_controller(lock_policy);
|
||||
//
|
||||
// etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot);
|
||||
// etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
|
||||
// etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Single_Shot);
|
||||
//
|
||||
// object.tick_list.clear();
|
||||
// free_tick_list1.clear();
|
||||
// free_tick_list2.clear();
|
||||
//
|
||||
// timer_controller.start(id1);
|
||||
// timer_controller.start(id3);
|
||||
// timer_controller.start(id2);
|
||||
//
|
||||
// timer_controller.enable(true);
|
||||
//
|
||||
// ticks = 0;
|
||||
//
|
||||
// const uint32_t step = 1UL;
|
||||
//
|
||||
// while (ticks <= 100U)
|
||||
// {
|
||||
// ticks += step;
|
||||
// timer_controller.tick(step);
|
||||
// }
|
||||
//
|
||||
// std::vector<uint64_t> compare1 = {37};
|
||||
// std::vector<uint64_t> compare2 = {23};
|
||||
// std::vector<uint64_t> compare3 = {11};
|
||||
//
|
||||
// CHECK(object.tick_list.size() != 0);
|
||||
// CHECK(free_tick_list1.size() != 0);
|
||||
// CHECK(free_tick_list2.size() != 0);
|
||||
//
|
||||
// CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size());
|
||||
// CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size());
|
||||
// CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size());
|
||||
//}
|
||||
etl::intrusive_timer timer_controller(lock_policy);
|
||||
|
||||
etl::timer_config config1(100, etl::timer::mode::Single_Shot);
|
||||
CallbackDelegate callback_delegate1 = CallbackDelegate::create(global_callback);
|
||||
CallbackTimer callback_timer1(callback_delegate1, config1);
|
||||
|
||||
etl::timer_config config2(23, etl::timer::mode::Single_Shot);
|
||||
CallbackDelegate callback_delegate2 = CallbackDelegate::create<Object, &Object::member, object>();
|
||||
CallbackTimer callback_timer2(callback_delegate2, config2);
|
||||
|
||||
etl::timer_config config3(11, etl::timer::mode::Single_Shot);
|
||||
MessageTimer callback_timer3(config3, message_processor, callback_message);
|
||||
|
||||
CHECK_TRUE(timer_controller.register_timer(callback_timer1));
|
||||
CHECK_TRUE(timer_controller.register_timer(callback_timer2));
|
||||
CHECK_TRUE(timer_controller.register_timer(callback_timer3));
|
||||
|
||||
// Get the modified id of the timers after registration.
|
||||
etl::timer::id::type config1_id = callback_timer1.get_id();
|
||||
etl::timer::id::type config2_id = callback_timer2.get_id();
|
||||
etl::timer::id::type config3_id = callback_timer3.get_id();
|
||||
|
||||
timer_controller.start(callback_timer1);
|
||||
timer_controller.start(callback_timer3);
|
||||
timer_controller.start(callback_timer2);
|
||||
|
||||
timer_controller.enable(true);
|
||||
|
||||
ticks = 0;
|
||||
|
||||
const uint32_t step = 1UL;
|
||||
|
||||
while (ticks <= 100U)
|
||||
{
|
||||
ticks += step;
|
||||
timer_controller.tick(step);
|
||||
}
|
||||
|
||||
CHECK_TRUE(global_callback_called);
|
||||
CHECK_EQUAL((int)config1_id, (int)global_config->get_id());
|
||||
CHECK_EQUAL(config1.get_mode(), global_config->get_mode());
|
||||
CHECK_EQUAL(config1.get_period(), global_config->get_period());
|
||||
|
||||
CHECK_TRUE(object.member_callback_called);
|
||||
CHECK_EQUAL((int)config2_id, (int)object.member_config->get_id());
|
||||
CHECK_EQUAL(config2.get_mode(), object.member_config->get_mode());
|
||||
CHECK_EQUAL(config2.get_period(), object.member_config->get_period());
|
||||
|
||||
CHECK_TRUE(message_processor.message_callback_called);
|
||||
CHECK_EQUAL((int)config3_id, (int)message_processor.message_config->get_id());
|
||||
CHECK_EQUAL(config3.get_mode(), message_processor.message_config->get_mode());
|
||||
CHECK_EQUAL(config3.get_period(), message_processor.message_config->get_period());
|
||||
CHECK_EQUAL(callback_message.value, message_processor.value);
|
||||
|
||||
// std::vector<uint64_t> compare1 = {37};
|
||||
// std::vector<uint64_t> compare2 = {23};
|
||||
// std::vector<uint64_t> compare3 = {11};
|
||||
|
||||
// CHECK(object.tick_list.size() != 0);
|
||||
// CHECK(free_tick_list1.size() != 0);
|
||||
// CHECK(free_tick_list2.size() != 0);
|
||||
|
||||
// CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size());
|
||||
// CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size());
|
||||
// CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size());
|
||||
}
|
||||
|
||||
// //*************************************************************************
|
||||
// TEST(message_timer_one_shot_after_timeout)
|
||||
|
||||
@ -33,6 +33,49 @@ SOFTWARE.
|
||||
|
||||
namespace
|
||||
{
|
||||
//*******************************************
|
||||
class etl_unit_test_intrusive_timer
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
void register_timer(etl::private_timer::timer_register_list& register_list, etl::timer_node& timer_)
|
||||
{
|
||||
timer_.set_id(get_next_id(register_list));
|
||||
register_list.insert(&timer_);
|
||||
timer_.set_owner(this);
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
etl::timer::id::type get_next_id(etl::private_timer::timer_register_list& register_list) ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer::id::type next_id = 0; // IDs start at 0
|
||||
|
||||
etl::timer_node* timer = register_list.first();
|
||||
|
||||
while (timer != register_list.end())
|
||||
{
|
||||
if (timer->get_id() == next_id)
|
||||
{
|
||||
// Already in use, so increment next_id and continue checking
|
||||
++next_id;
|
||||
}
|
||||
else if (timer->get_id() > next_id)
|
||||
{
|
||||
// Found a gap in the IDs, so return the next_id
|
||||
return next_id;
|
||||
}
|
||||
|
||||
timer = register_list.next(timer);
|
||||
}
|
||||
|
||||
// We never found a gap, so return the next available ID
|
||||
return next_id;
|
||||
}
|
||||
};
|
||||
|
||||
etl_unit_test_intrusive_timer test_intrusive_timer;
|
||||
|
||||
SUITE(test_timer_lists)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -55,11 +98,14 @@ namespace
|
||||
CHECK_TRUE(register_list.first() == register_list.end());
|
||||
|
||||
// Add the timers to the list.
|
||||
register_list.insert(&timer1);
|
||||
register_list.insert(&timer2);
|
||||
register_list.insert(&timer3);
|
||||
register_list.insert(&timer4);
|
||||
register_list.insert(&timer5);
|
||||
test_intrusive_timer.register_timer(register_list, timer1);
|
||||
test_intrusive_timer.register_timer(register_list, timer2);
|
||||
test_intrusive_timer.register_timer(register_list, timer3);
|
||||
test_intrusive_timer.register_timer(register_list, timer4);
|
||||
test_intrusive_timer.register_timer(register_list, timer5);
|
||||
|
||||
auto p1 = register_list.first();
|
||||
auto p2 = &timer1;
|
||||
|
||||
CHECK_FALSE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == &timer1);
|
||||
@ -216,50 +262,6 @@ namespace
|
||||
CHECK_EQUAL(timer4.get_config().get_period() - timer1.get_config().get_period(), timer4.get_delta());
|
||||
CHECK_EQUAL(timer5.get_config().get_period() - timer2.get_config().get_period(), timer5.get_delta());
|
||||
|
||||
// Remove a timer that is not in the list.
|
||||
active_list.remove(&timer6);
|
||||
|
||||
// Search the list to ensure the other timers are still present.
|
||||
timer1_found = false;
|
||||
timer2_found = false;
|
||||
timer3_found = false;
|
||||
timer4_found = false;
|
||||
timer5_found = false;
|
||||
|
||||
timer = active_list.first();
|
||||
|
||||
while (timer != active_list.end())
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
timer1_found = true;
|
||||
}
|
||||
else if (timer == &timer2)
|
||||
{
|
||||
timer2_found = true;
|
||||
}
|
||||
else if (timer == &timer3)
|
||||
{
|
||||
timer3_found = true;
|
||||
}
|
||||
else if (timer == &timer4)
|
||||
{
|
||||
timer4_found = true;
|
||||
}
|
||||
else if (timer == &timer5)
|
||||
{
|
||||
timer5_found = true;
|
||||
}
|
||||
|
||||
timer = active_list.next(timer);
|
||||
}
|
||||
|
||||
// Check the deltas are still correct.
|
||||
CHECK_EQUAL(timer2.get_period(), timer2.get_delta());
|
||||
CHECK_EQUAL(timer1.get_period() - timer3.get_period(), timer1.get_delta());
|
||||
CHECK_EQUAL(timer4.get_period() - timer1.get_period(), timer4.get_delta());
|
||||
CHECK_EQUAL(timer5.get_period() - timer2.get_period(), timer5.get_delta());
|
||||
|
||||
// Clear the list.
|
||||
active_list.clear();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user