From b0a616e21e98334d8efa240f9cb326be431658a2 Mon Sep 17 00:00:00 2001 From: erling Date: Tue, 15 Oct 2024 15:46:52 -0700 Subject: [PATCH] Increment microstep when scheduling action with 0 delay (#67) --- src/action.c | 8 +- src/tag.c | 142 +----------------------------- test/unit/action_microstep_test.c | 103 ++++++++++++++++++++++ 3 files changed, 108 insertions(+), 145 deletions(-) create mode 100644 test/unit/action_microstep_test.c diff --git a/src/action.c b/src/action.c index 0b29a015..c44ac647 100644 --- a/src/action.c +++ b/src/action.c @@ -46,9 +46,9 @@ void Action_ctor(Action *self, TriggerType type, interval_t min_offset, interval lf_ret_t LogicalAction_schedule(Action *self, interval_t offset, const void *value) { Environment *env = self->super.parent->env; Scheduler *sched = &env->scheduler; - tag_t tag = {.time = env->current_tag.time + self->min_offset + offset, .microstep = 0}; + tag_t proposed_tag = lf_delay_tag(env->current_tag, offset); tag_t earliest_allowed = lf_delay_tag(self->previous_event, self->min_spacing); - if (lf_tag_compare(tag, earliest_allowed) < 0) { + if (lf_tag_compare(proposed_tag, earliest_allowed) < 0) { return LF_INVALID_TAG; } @@ -59,9 +59,9 @@ lf_ret_t LogicalAction_schedule(Action *self, interval_t offset, const void *val return LF_INVALID_VALUE; } - int ret = sched->schedule_at(sched, (Trigger *)self, tag); + int ret = sched->schedule_at(sched, (Trigger *)self, proposed_tag); if (ret == 0) { - self->previous_event = tag; + self->previous_event = proposed_tag; } return ret; } diff --git a/src/tag.c b/src/tag.c index dab4dc8d..2a1eccb9 100644 --- a/src/tag.c +++ b/src/tag.c @@ -100,144 +100,4 @@ tag_t lf_delay_strict(tag_t tag, interval_t interval) { result.microstep = UINT_MAX; } return result; -} - -// instant_t lf_time_logical(void *env) { return ((Environment *)env)->current_tag.time; } - -// interval_t lf_time_logical_elapsed(void *env) { return lf_time_logical(env) - start_time; } - -// instant_t lf_time_physical(void) { -// instant_t now = MSEC(0); -// // Get the current clock value -// return now; -// } - -// instant_t lf_time_physical_elapsed(void) { return lf_time_physical() - start_time; } - -// instant_t lf_time_start(void) { return start_time; } - -// size_t lf_readable_time(char *buffer, instant_t time) { -// if (time <= (instant_t)0) { -// snprintf(buffer, 2, "0"); -// return 1; -// } -// char *original_buffer = buffer; -// bool lead = false; // Set to true when first clause has been printed. -// if (time > WEEKS(1)) { -// lead = true; -// size_t printed = lf_comma_separated_time(buffer, time / WEEKS(1)); -// time = time % WEEKS(1); -// buffer += printed; -// snprintf(buffer, 7, " weeks"); -// buffer += 6; -// } -// if (time > DAYS(1)) { -// if (lead == true) { -// snprintf(buffer, 3, ", "); -// buffer += 2; -// } -// lead = true; -// size_t printed = lf_comma_separated_time(buffer, time / DAYS(1)); -// time = time % DAYS(1); -// buffer += printed; -// snprintf(buffer, 3, " d"); -// buffer += 2; -// } -// if (time > HOURS(1)) { -// if (lead == true) { -// snprintf(buffer, 3, ", "); -// buffer += 2; -// } -// lead = true; -// size_t printed = lf_comma_separated_time(buffer, time / HOURS(1)); -// time = time % HOURS(1); -// buffer += printed; -// snprintf(buffer, 3, " h"); -// buffer += 2; -// } -// if (time > MINUTES(1)) { -// if (lead == true) { -// snprintf(buffer, 3, ", "); -// buffer += 2; -// } -// lead = true; -// size_t printed = lf_comma_separated_time(buffer, time / MINUTES(1)); -// time = time % MINUTES(1); -// buffer += printed; -// snprintf(buffer, 5, " min"); -// buffer += 4; -// } -// if (time > SECONDS(1)) { -// if (lead == true) { -// snprintf(buffer, 3, ", "); -// buffer += 2; -// } -// lead = true; -// size_t printed = lf_comma_separated_time(buffer, time / SECONDS(1)); -// time = time % SECONDS(1); -// buffer += printed; -// snprintf(buffer, 3, " s"); -// buffer += 2; -// } -// if (time > (instant_t)0) { -// if (lead == true) { -// snprintf(buffer, 3, ", "); -// buffer += 2; -// } -// const char *units = "ns"; -// if (time % MSEC(1) == (instant_t)0) { -// units = "ms"; -// time = time / MSEC(1); -// } else if (time % USEC(1) == (instant_t)0) { -// units = "us"; -// time = time / USEC(1); -// } -// size_t printed = lf_comma_separated_time(buffer, time); -// buffer += printed; -// snprintf(buffer, 4, " %s", units); -// buffer += strlen(units) + 1; -// } -// return (buffer - original_buffer); -// } - -// size_t lf_comma_separated_time(char *buffer, instant_t time) { -// size_t result = 0; // The number of characters printed. -// // If the number is zero, print it and return. -// if (time == (instant_t)0) { -// snprintf(buffer, 2, "0"); -// return 1; -// } -// // If the number is negative, print a minus sign. -// if (time < (instant_t)0) { -// snprintf(buffer, 2, "-"); -// buffer++; -// result++; -// } -// int count = 0; -// // Assume the time value is no larger than 64 bits. -// instant_t clauses[7]; -// while (time > (instant_t)0) { -// clauses[count++] = time; -// time = time / 1000; -// } -// // Highest order clause should not be filled with zeros. -// instant_t to_print = clauses[--count] % 1000; -// snprintf(buffer, 5, "%lld", (long long)to_print); -// if (to_print >= 100LL) { -// buffer += 3; -// result += 3; -// } else if (to_print >= 10LL) { -// buffer += 2; -// result += 2; -// } else { -// buffer += 1; -// result += 1; -// } -// while (count-- > 0) { -// to_print = clauses[count] % 1000LL; -// snprintf(buffer, 8, ",%03lld", (long long)to_print); -// buffer += 4; -// result += 4; -// } -// return result; -// } +} \ No newline at end of file diff --git a/test/unit/action_microstep_test.c b/test/unit/action_microstep_test.c new file mode 100644 index 00000000..a1e64496 --- /dev/null +++ b/test/unit/action_microstep_test.c @@ -0,0 +1,103 @@ +#include "reactor-uc/reactor-uc.h" +#include "unity.h" + +typedef struct { + LogicalAction super; + int buffer[1]; + + Reaction *sources[1]; + Reaction *effects[1]; +} MyAction; + +typedef struct MyStartup MyStartup; + +struct MyStartup { + Startup super; + Reaction *effects_[1]; +}; + +typedef struct { + Reaction super; + Trigger *effects[1]; +} MyReaction; + +struct MyReactor { + Reactor super; + MyReaction my_reaction; + MyAction my_action; + MyStartup startup; + Reaction *_reactions[1]; + Trigger *_triggers[2]; + int cnt; +}; + +void MyAction_ctor(MyAction *self, struct MyReactor *parent) { + LogicalAction_ctor(&self->super, MSEC(0), MSEC(0), &parent->super, self->sources, 1, self->effects, 1, &self->buffer, + sizeof(self->buffer[0]), 2); +} + +void MyStartup_ctor(struct MyStartup *self, Reactor *parent, Reaction *effects) { + self->effects_[0] = effects; + Startup_ctor(&self->super, parent, self->effects_, 1); +} + +void action_handler(Reaction *_self) { + struct MyReactor *self = (struct MyReactor *)_self->parent; + Environment *env = self->super.env; + MyAction *my_action = &self->my_action; + if (self->cnt == 0) { + TEST_ASSERT_EQUAL(lf_is_present(my_action), false); + } else { + TEST_ASSERT_EQUAL(lf_is_present(my_action), true); + } + + printf("Hello World\n"); + printf("Action = %d\n", lf_get(my_action)); + if (self->cnt > 0) { + TEST_ASSERT_EQUAL(self->cnt, lf_get(my_action)); + TEST_ASSERT_EQUAL(self->cnt, env->current_tag.microstep); + TEST_ASSERT_EQUAL(true, lf_is_present(my_action)); + } else { + TEST_ASSERT_EQUAL(false, lf_is_present(my_action)); + } + + TEST_ASSERT_EQUAL(0, env->get_elapsed_logical_time(env)); + + if (self->cnt < 100) { + lf_schedule(my_action, ++self->cnt, 0); + } +} + +void MyReaction_ctor(MyReaction *self, Reactor *parent) { + Reaction_ctor(&self->super, parent, action_handler, self->effects, 1, 0); +} + +void MyReactor_ctor(struct MyReactor *self, Environment *env) { + self->_reactions[0] = (Reaction *)&self->my_reaction; + self->_triggers[0] = (Trigger *)&self->startup; + self->_triggers[1] = (Trigger *)&self->my_action; + Reactor_ctor(&self->super, "MyReactor", env, NULL, NULL, 0, self->_reactions, 1, self->_triggers, 2); + MyAction_ctor(&self->my_action, self); + MyReaction_ctor(&self->my_reaction, &self->super); + MyStartup_ctor(&self->startup, &self->super, &self->my_reaction.super); + ACTION_REGISTER_EFFECT(self->my_action, self->my_reaction); + REACTION_REGISTER_EFFECT(self->my_reaction, self->my_action); + ACTION_REGISTER_SOURCE(self->my_action, self->my_reaction); + self->cnt = 0; +} + +void test_simple() { + struct MyReactor my_reactor; + Environment env; + Environment_ctor(&env, (Reactor *)&my_reactor); + MyReactor_ctor(&my_reactor, &env); + env.set_timeout(&env, SEC(1)); + env.assemble(&env); + env.start(&env); +} + +int main() { + UNITY_BEGIN(); + RUN_TEST(test_simple); + return UNITY_END(); +} \ No newline at end of file