Skip to content

Commit

Permalink
Merge pull request #487 from lf-lang/mutable
Browse files Browse the repository at this point in the history
Prevent a warning when the second timer event is after the timeout time.
  • Loading branch information
edwardalee authored Oct 3, 2024
2 parents 815696c + 693c5f5 commit 184567d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 23 deletions.
20 changes: 17 additions & 3 deletions core/lf_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,20 @@ int _lf_count_token_allocations;
#include "platform.h" // Enter/exit critical sections
#include "port.h" // Defines lf_port_base_t.

lf_token_t* _lf_tokens_allocated_in_reactions = NULL;
/**
* @brief List of tokens created within reactions that must be freed.
*
* Tokens created by lf_writable_copy, which is automatically invoked
* when an input is mutable, must have their reference count decremented
* at the end of a tag (or the beginning of the next tag).
* Otherwise, their memory could leak. If they are passed on to
* an output or to a call to lf_schedule during the reaction, then
* those will also result in incremented reference counts, enabling
* the token to live on until used. For example, a new token created
* by lf_writable_copy could become the new template token for an output
* via a call to lf_set.
*/
static lf_token_t* _lf_tokens_allocated_in_reactions = NULL;

////////////////////////////////////////////////////////////////////
//// Global variables not visible outside this file.
Expand Down Expand Up @@ -197,6 +210,8 @@ lf_token_t* _lf_new_token(token_type_t* type, void* value, size_t length) {
if (hashset_iterator_next(iterator) >= 0) {
result = hashset_iterator_value(iterator);
hashset_remove(_lf_token_recycling_bin, result);
// Make sure there isn't a previous value.
result->value = NULL;
LF_PRINT_DEBUG("_lf_new_token: Retrieved token from the recycling bin: %p", (void*)result);
}
free(iterator);
Expand Down Expand Up @@ -352,8 +367,7 @@ token_freed _lf_done_using(lf_token_t* token) {

void _lf_free_token_copies() {
while (_lf_tokens_allocated_in_reactions != NULL) {
lf_token_t* next = _lf_tokens_allocated_in_reactions->next;
_lf_done_using(_lf_tokens_allocated_in_reactions);
_lf_tokens_allocated_in_reactions = next;
_lf_tokens_allocated_in_reactions = _lf_tokens_allocated_in_reactions->next;
}
}
16 changes: 10 additions & 6 deletions core/reactor_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,16 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) {

// Get an event_t struct to put on the event queue.
// Recycle event_t structs, if possible.
event_t* e = lf_get_new_event(env);
e->trigger = timer;
e->base.tag = (tag_t){.time = lf_time_logical(env) + delay, .microstep = 0};
// NOTE: No lock is being held. Assuming this only happens at startup.
pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e);
tracepoint_schedule(env, timer, delay); // Trace even though schedule is not called.
tag_t next_tag = (tag_t){.time = lf_time_logical(env) + delay, .microstep = 0};
// Do not schedule the next event if it is after the timeout.
if (!lf_is_tag_after_stop_tag(env, next_tag)) {
event_t* e = lf_get_new_event(env);
e->trigger = timer;
e->base.tag = next_tag;
// NOTE: No lock is being held. Assuming this only happens at startup.
pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e);
tracepoint_schedule(env, timer, delay); // Trace even though schedule is not called.
}
}

void _lf_initialize_timers(environment_t* env) {
Expand Down
14 changes: 0 additions & 14 deletions include/core/lf_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,6 @@ typedef struct lf_port_base_t {
//////////////////////////////////////////////////////////
//// Global variables

/**
* @brief List of tokens created within reactions that must be freed.
* Tokens created by lf_writable_copy, which is automatically invoked
* when an input is mutable, must have their reference count decremented
* at the end of a tag (or the beginning of the next tag).
* Otherwise, their memory could leak. If they are passed on to
* an output or to a call to lf_schedule during the reaction, then
* those will also result in incremented reference counts, enabling
* the token to live on until used. For example, a new token created
* by lf_writable_copy could become the new template token for an output
* via a call to lf_set.
*/
extern lf_token_t* _lf_tokens_allocated_in_reactions;

/**
* Counter used to issue a warning if memory is
* allocated for tokens and never freed. Note that
Expand Down

0 comments on commit 184567d

Please sign in to comment.