reactor-c
C Runtime for Lingua Franca
Loading...
Searching...
No Matches
tag.c File Reference

Implementation of time and tag functions for Lingua Franca programs. More...

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "tag.h"
#include "util.h"
#include "low_level_platform.h"
#include "environment.h"
#include "reactor.h"
#include "lf_types.h"
#include "clock.h"

Typedefs

typedef enum _lf_time_type _lf_time_type
 

Enumerations

enum  _lf_time_type {
  LF_LOGICAL , LF_PHYSICAL , LF_ELAPSED_LOGICAL , LF_ELAPSED_PHYSICAL ,
  LF_START
}
 

Functions

tag_t lf_tag (void *env)
 
instant_t lf_time_add (instant_t a, interval_t b)
 Return the sum of an interval and an instant, saturating on overflow and underflow.
 
tag_t lf_tag_add (tag_t a, tag_t b)
 
int lf_tag_compare (tag_t tag1, tag_t tag2)
 
tag_t lf_delay_tag (tag_t tag, interval_t interval)
 
tag_t lf_delay_strict (tag_t tag, interval_t interval)
 
instant_t lf_time_logical (void *env)
 
interval_t lf_time_logical_elapsed (void *env)
 
instant_t lf_time_physical (void)
 
instant_t lf_time_physical_elapsed (void)
 
instant_t lf_time_start (void)
 
size_t lf_readable_time (char *buffer, instant_t time)
 
size_t lf_comma_separated_time (char *buffer, instant_t time)
 

Variables

instant_t start_time = NEVER
 

Detailed Description

Implementation of time and tag functions for Lingua Franca programs.

Author
Edward A. Lee
Soroush Bateni
Hou Seng (Steven) Wong

Typedef Documentation

◆ _lf_time_type

An enum for specifying the desired tag when calling "lf_time"

Enumeration Type Documentation

◆ _lf_time_type

An enum for specifying the desired tag when calling "lf_time"

Enumerator
LF_LOGICAL 
LF_PHYSICAL 
LF_ELAPSED_LOGICAL 
LF_ELAPSED_PHYSICAL 
LF_START 

Function Documentation

◆ lf_comma_separated_time()

size_t lf_comma_separated_time ( char * buffer,
instant_t time )

Print a non-negative time value in nanoseconds with commas separating thousands into the specified buffer. Ideally, this would use the locale to use periods if appropriate, but I haven't found a sufficiently portable way to do that.

Parameters
bufferA buffer long enough to contain a string like "9,223,372,036,854,775,807".
timeA time value.
Returns
The number of characters written (not counting the null terminator).

◆ lf_delay_strict()

tag_t lf_delay_strict ( tag_t tag,
interval_t interval )

Return the latest tag strictly less than the specified tag plus the interval, unless tag is NEVER or interval is negative (including NEVER), in which case return the tag unmodified. Any interval less than 0 (including NEVER) is interpreted as "no delay", whereas an interval equal to 0 is interpreted as one microstep delay. If the time sum overflows, saturate the time value at FOREVER. For example:

  • if tag = (t, 0) and interval = 10, return (t + 10 - 1, UINT_MAX)
  • if tag = (t, 0) and interval = 0, return (t, 0)
  • if tag = (t, 0) and interval = NEVER, return (t, 0)
  • if tag = (FOREVER, 0) and interval = 10, return (FOREVER, 0)
Parameters
tagThe tag to increment.
intervalThe time interval.

◆ lf_delay_tag()

tag_t lf_delay_tag ( tag_t tag,
interval_t interval )

Delay a tag by the specified time interval to realize the "after" keyword. Any interval less than 0 (including NEVER) is interpreted as "no delay", whereas an interval equal to 0 is interpreted as one microstep delay. If the time field of the tag is NEVER or the interval is negative, return the unmodified tag. If the time interval is 0LL, add one to the microstep, leave the time field alone, and return the result. Otherwise, add the interval to the time field of the tag and reset the microstep to 0. If the sum overflows, saturate the time value at FOREVER. For example:

  • if tag = (t, 0) and interval = 10, return (t + 10, 0)
  • if tag = (t, 0) and interval = 0, return (t, 1)
  • if tag = (t, 0) and interval = NEVER, return (t, 0)
  • if tag = (FOREVER, 0) and interval = 10, return (FOREVER, 0)
Parameters
tagThe tag to increment.
intervalThe time interval.

◆ lf_readable_time()

size_t lf_readable_time ( char * buffer,
instant_t time )

Store into the specified buffer a string giving a human-readable rendition of the specified time. The buffer must have length at least equal to LF_TIME_BUFFER_LENGTH. The format is:

x weeks, x d, x hr, x min, x s, x unit

where each x is a string of numbers with commas inserted if needed every three numbers and unit is ns, us, or ms.

Parameters
bufferThe buffer into which to write the string.
timeThe time to write.
Returns
The number of characters written (not counting the null terminator).

◆ lf_tag()

tag_t lf_tag ( void * env)

Return the current tag, a logical time, microstep pair.

Parameters
envA pointer to the environment from which we want the current tag.

◆ lf_tag_add()

tag_t lf_tag_add ( tag_t a,
tag_t b )

Add two tags. If either tag has has NEVER or FOREVER in its time field, then return NEVER_TAG or FOREVER_TAG, respectively. Also return NEVER_TAG or FOREVER_TAG if the result underflows or overflows when adding the times. If the microstep overflows, also return FOREVER_TAG. If the time field of the second tag is greater than 0, then the microstep of the first tag is reset to 0 before adding. This models the delay semantics in LF and makes this addition operation non-commutative.

Parameters
aThe first tag.
bThe second tag.

◆ lf_tag_compare()

int lf_tag_compare ( tag_t tag1,
tag_t tag2 )

Compare two tags. Return -1 if the first is less than the second, 0 if they are equal, and +1 if the first is greater than the second. A tag is greater than another if its time is greater or if its time is equal and its microstep is greater.

Parameters
tag1
tag2
Returns
-1, 0, or 1 depending on the relation.

◆ lf_time_add()

instant_t lf_time_add ( instant_t a,
interval_t b )

Return the sum of an interval and an instant, saturating on overflow and underflow.

Parameters
a
b
Returns
instant_t

◆ lf_time_logical()

instant_t lf_time_logical ( void * env)

Return the current logical time in nanoseconds. On many platforms, this is the number of nanoseconds since January 1, 1970, but it is actually platform dependent.

Parameters
envThe environment from which we want the current logical time.
Returns
A time instant.

◆ lf_time_logical_elapsed()

interval_t lf_time_logical_elapsed ( void * env)

Return the elapsed logical time in nanoseconds since the start of execution.

Parameters
envThe environment from which we want the elapsed logical time.
Returns
A time interval.

◆ lf_time_physical()

instant_t lf_time_physical ( void )

Return the current physical time in nanoseconds. On many platforms, this is the number of nanoseconds since January 1, 1970, but it is actually platform dependent.

Returns
A time instant.

◆ lf_time_physical_elapsed()

instant_t lf_time_physical_elapsed ( void )

Return the elapsed physical time in nanoseconds. This is the time returned by lf_time_physical(void) minus the physical start time as measured by lf_time_physical(void) when the program was started.

◆ lf_time_start()

instant_t lf_time_start ( void )

Return the physical and logical time of the start of execution in nanoseconds. On many platforms, this is the number of nanoseconds since January 1, 1970, but it is actually platform dependent.

Returns
A time instant.

Variable Documentation

◆ start_time

instant_t start_time = NEVER

The start time read from the trace file.