diff --git a/include/reactor-uc/action.h b/include/reactor-uc/action.h index 3c3f3bd3d..ea18c5afa 100644 --- a/include/reactor-uc/action.h +++ b/include/reactor-uc/action.h @@ -19,6 +19,8 @@ struct Action { TriggerEffects effects; // The reactions triggered by this Action. TriggerSources sources; // The reactions that can write to this Action. EventPayloadPool payload_pool; // Pool of memory for the data associated with the events scheduled on this action. + size_t event_bound; + size_t events_scheduled; /** * @brief Schedule an event on this action. */ diff --git a/include/reactor-uc/macros.h b/include/reactor-uc/macros.h index 1d7e53c30..80720d7f5 100644 --- a/include/reactor-uc/macros.h +++ b/include/reactor-uc/macros.h @@ -220,21 +220,21 @@ #define DEFINE_ACTION_STRUCT(...) DEFINE_ACTION_STRUCT_CHOOSER(__VA_ARGS__)(__VA_ARGS__) -#define DEFINE_ACTION_CTOR_WITH_VALUE(ActionName, ActionType, MinDelay, EffectSize, SourceSize, BufferType, \ - BufferSize) \ - void ActionName##_ctor(ActionName *self, Reactor *parent) { \ +#define DEFINE_ACTION_CTOR_WITH_VALUE(ActionName, ActionType, MinDelay, EffectSize, SourceSize, EventBound, \ + BufferType) \ + \ void ActionName##_ctor(ActionName *self, Reactor *parent) { \ Action_ctor(&self->super, ActionType, MinDelay, parent, self->sources, (SourceSize), self->effects, (EffectSize), \ - &self->value, sizeof(BufferType), (void *)&self->payload_buf, self->payload_used_buf, (BufferSize)); \ + &self->value, sizeof(BufferType), (void *)&self->payload_buf, self->payload_used_buf, (EventBound)); \ } -#define DEFINE_ACTION_CTOR_WITHOUT_VALUE(ActionName, ActionType, MinDelay, EffectSize, SourceSize) \ +#define DEFINE_ACTION_CTOR_WITHOUT_VALUE(ActionName, ActionType, MinDelay, EffectSize, SourceSize, EventBound) \ void ActionName##_ctor(ActionName *self, Reactor *parent) { \ Action_ctor(&self->super, ActionType, (MinDelay), parent, self->sources, (SourceSize), self->effects, \ - (EffectSize), NULL, 0, NULL, NULL, 0); \ + (EffectSize), NULL, 0, NULL, NULL, (EventBound)); \ } #define DEFINE_ACTION_CTOR_CHOOSER(...) \ - GET_ARG8(__VA_ARGS__, DEFINE_ACTION_CTOR_WITH_VALUE, NULL, DEFINE_ACTION_CTOR_WITHOUT_VALUE) + GET_ARG8(__VA_ARGS__, DEFINE_ACTION_CTOR_WITH_VALUE, DEFINE_ACTION_CTOR_WITHOUT_VALUE) #define DEFINE_ACTION_CTOR(...) DEFINE_ACTION_CTOR_CHOOSER(__VA_ARGS__)(__VA_ARGS__) diff --git a/src/action.c b/src/action.c index f6f050285..88716d59f 100644 --- a/src/action.c +++ b/src/action.c @@ -17,6 +17,8 @@ void Action_prepare(Trigger *self, Event *event) { self->is_present = true; memcpy(act->value_ptr, event->payload, act->payload_pool.size); + act->events_scheduled--; + sched->register_for_cleanup(sched, self); for (size_t i = 0; i < act->effects.size; i++) { @@ -49,6 +51,11 @@ lf_ret_t Action_schedule(Action *self, interval_t offset, const void *value) { return LF_ERR; } + if (self->events_scheduled >= self->event_bound) { + LF_ERR(TRIG, "Scheduled action to often bound: %i", self->event_bound); + return LF_ERR; + } + if (value != NULL) { ret = self->super.payload_pool->allocate(self->super.payload_pool, &payload); if (ret != LF_OK) { @@ -71,6 +78,7 @@ lf_ret_t Action_schedule(Action *self, interval_t offset, const void *value) { Event event = EVENT_INIT(tag, (Trigger *)self, payload); ret = sched->schedule_at_locked(sched, &event); + self->events_scheduled++; if (self->type == PHYSICAL_ACTION) { env->platform->new_async_event(env->platform); @@ -83,12 +91,18 @@ lf_ret_t Action_schedule(Action *self, interval_t offset, const void *value) { void Action_ctor(Action *self, ActionType type, interval_t min_offset, Reactor *parent, Reaction **sources, size_t sources_size, Reaction **effects, size_t effects_size, void *value_ptr, size_t value_size, - void *payload_buf, bool *payload_used_buf, size_t payload_buf_capacity) { - EventPayloadPool_ctor(&self->payload_pool, payload_buf, payload_used_buf, value_size, payload_buf_capacity); + void *payload_buf, bool *payload_used_buf, size_t event_bound) { + int capacity = 0; + if (payload_buf != NULL) { + capacity = event_bound; + } + EventPayloadPool_ctor(&self->payload_pool, payload_buf, payload_used_buf, value_size, capacity); Trigger_ctor(&self->super, TRIG_ACTION, parent, &self->payload_pool, Action_prepare, Action_cleanup); self->type = type; self->value_ptr = value_ptr; self->min_offset = min_offset; + self->event_bound = event_bound; + self->events_scheduled = 0; self->schedule = Action_schedule; self->sources.reactions = sources; self->sources.num_registered = 0; diff --git a/src/event.c b/src/event.c index eba27005f..ed346e5b6 100644 --- a/src/event.c +++ b/src/event.c @@ -30,9 +30,13 @@ void EventPayloadPool_ctor(EventPayloadPool *self, char *buffer, bool *used, siz self->used = used; self->capacity = capacity; self->size = size; - for (size_t i = 0; i < capacity; i++) { - self->used[i] = false; + + if (self->used != NULL) { + for (size_t i = 0; i < capacity; i++) { + self->used[i] = false; + } } + self->allocate = EventPayloadPool_allocate; self->free = EventPayloadPool_free; } diff --git a/test/unit/empty_action_test.c b/test/unit/empty_action_test.c index cc6cbe172..d89e415be 100644 --- a/test/unit/empty_action_test.c +++ b/test/unit/empty_action_test.c @@ -2,7 +2,7 @@ #include "unity.h" DEFINE_ACTION_STRUCT(MyAction, LOGICAL_ACTION, 1, 1); -DEFINE_ACTION_CTOR(MyAction, LOGICAL_ACTION, MSEC(0), 1, 1); +DEFINE_ACTION_CTOR(MyAction, PHYSICAL_ACTION, MSEC(0), 1, 1, 6); DEFINE_STARTUP_STRUCT(MyStartup, 1); DEFINE_STARTUP_CTOR(MyStartup, 1) DEFINE_REACTION_STRUCT(MyReactor, 0, 1);