rcl  master
C API providing common ROS client library functionality.
Classes | Typedefs | Functions
timer.h File Reference
#include <stdbool.h>
#include "rcl/allocator.h"
#include "rcl/context.h"
#include "rcl/guard_condition.h"
#include "rcl/macros.h"
#include "rcl/time.h"
#include "rcl/types.h"
#include "rmw/rmw.h"
Include dependency graph for timer.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  rcl_timer_t
 Structure which encapsulates a ROS Timer. More...
 

Typedefs

typedef struct rcl_timer_t rcl_timer_t
 Structure which encapsulates a ROS Timer. More...
 
typedef void(* rcl_timer_callback_t) (rcl_timer_t *, int64_t)
 User callback signature for timers. More...
 

Functions

rcl_timer_t rcl_get_zero_initialized_timer (void)
 Return a zero initialized timer. More...
 
rcl_ret_t rcl_timer_init (rcl_timer_t *timer, rcl_clock_t *clock, rcl_context_t *context, int64_t period, const rcl_timer_callback_t callback, rcl_allocator_t allocator)
 Initialize a timer. More...
 
rcl_ret_t rcl_timer_fini (rcl_timer_t *timer)
 Finalize a timer. More...
 
rcl_ret_t rcl_timer_call (rcl_timer_t *timer)
 Call the timer's callback and set the last call time. More...
 
rcl_ret_t rcl_timer_clock (rcl_timer_t *timer, rcl_clock_t **clock)
 Retrieve the clock of the timer. More...
 
rcl_ret_t rcl_timer_is_ready (const rcl_timer_t *timer, bool *is_ready)
 Calculates whether or not the timer should be called. More...
 
rcl_ret_t rcl_timer_get_time_until_next_call (const rcl_timer_t *timer, int64_t *time_until_next_call)
 Calculate and retrieve the time until the next call in nanoseconds. More...
 
rcl_ret_t rcl_timer_get_time_since_last_call (const rcl_timer_t *timer, int64_t *time_since_last_call)
 Retrieve the time since the previous call to rcl_timer_call() occurred. More...
 
rcl_ret_t rcl_timer_get_period (const rcl_timer_t *timer, int64_t *period)
 Retrieve the period of the timer. More...
 
rcl_ret_t rcl_timer_exchange_period (const rcl_timer_t *timer, int64_t new_period, int64_t *old_period)
 Exchange the period of the timer and return the previous period. More...
 
rcl_timer_callback_t rcl_timer_get_callback (const rcl_timer_t *timer)
 Return the current timer callback. More...
 
rcl_timer_callback_t rcl_timer_exchange_callback (rcl_timer_t *timer, const rcl_timer_callback_t new_callback)
 Exchange the current timer callback and return the current callback. More...
 
rcl_ret_t rcl_timer_cancel (rcl_timer_t *timer)
 Cancel a timer. More...
 
rcl_ret_t rcl_timer_is_canceled (const rcl_timer_t *timer, bool *is_canceled)
 Retrieve the canceled state of a timer. More...
 
rcl_ret_t rcl_timer_reset (rcl_timer_t *timer)
 Reset a timer. More...
 
const rcl_allocator_trcl_timer_get_allocator (const rcl_timer_t *timer)
 Return the allocator for the timer. More...
 
rcl_guard_condition_trcl_timer_get_guard_condition (const rcl_timer_t *timer)
 Retrieve a guard condition used by the timer to wake the waitset when using ROSTime. More...
 

Typedef Documentation

◆ rcl_timer_t

typedef struct rcl_timer_t rcl_timer_t

Structure which encapsulates a ROS Timer.

◆ rcl_timer_callback_t

typedef void(* rcl_timer_callback_t) (rcl_timer_t *, int64_t)

User callback signature for timers.

The first argument the callback gets is a pointer to the timer. This can be used to cancel the timer, query the time until the next timer callback, exchange the callback with a different one, etc.

The only caveat is that the function rcl_timer_get_time_since_last_call() will return the time since just before this callback was called, not the previous call. Therefore the second argument given is the time since the previous callback was called, because that information is no longer accessible via the timer. The time since the last callback call is given in nanoseconds.

Function Documentation

◆ rcl_get_zero_initialized_timer()

rcl_timer_t rcl_get_zero_initialized_timer ( void  )

Return a zero initialized timer.

◆ rcl_timer_init()

rcl_ret_t rcl_timer_init ( rcl_timer_t timer,
rcl_clock_t clock,
rcl_context_t context,
int64_t  period,
const rcl_timer_callback_t  callback,
rcl_allocator_t  allocator 
)

Initialize a timer.

A timer consists of a clock, a callback function and a period. A timer can be added to a wait set and waited on, such that the wait set will wake up when a timer is ready to be executed.

A timer simply holds state and does not automatically call callbacks. It does not create any threads, register interrupts, or consume signals. For blocking behavior it can be used in conjunction with a wait set and rcl_wait(). When rcl_timer_is_ready() returns true, the timer must still be called explicitly using rcl_timer_call().

The timer handle must be a pointer to an allocated and zero initialized rcl_timer_t struct. Calling this function on an already initialized timer will fail. Calling this function on a timer struct which has been allocated but not zero initialized is undefined behavior.

The clock handle must be a pointer to an initialized rcl_clock_t struct. The life time of the clock must exceed the life time of the timer.

The period is a non-negative duration (rather an absolute time in the future). If the period is 0 then it will always be ready.

The callback is an optional argument. Valid inputs are either a pointer to the function callback, or NULL to indicate that no callback will be stored in rcl. If the callback is NULL, the caller client library is responsible for firing the timer callback. Else, it must be a function which returns void and takes two arguments, the first being a pointer to the associated timer, and the second a int64_t which is the time since the previous call, or since the timer was created if it is the first call to the callback.

Expected usage:

#include <rcl/rcl.h>
void my_timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
// Do timer work...
// Optionally reconfigure, cancel, or reset the timer...
}
rcl_context_t * context; // initialized previously by rcl_init()...
rcl_ret_t ret = rcl_clock_init(RCL_STEADY_TIME, &clock, &allocator);
// ... error handling
&timer, &clock, context, RCL_MS_TO_NS(100), my_timer_callback, allocator);
// ... error handling, use the timer with a wait set, or poll it manually, then cleanup
ret = rcl_timer_fini(&timer);
// ... error handling

Attribute Adherence
Allocates Memory Yes
Thread-Safe No
Uses Atomics Yes
Lock-Free Yes [1][2][3]

[1] if atomic_is_lock_free() returns true for atomic_uintptr_t

[2] if atomic_is_lock_free() returns true for atomic_uint_least64_t

[3] if atomic_is_lock_free() returns true for atomic_bool

Parameters
[in,out]timerthe timer handle to be initialized
[in]clockthe clock providing the current time
[in]contextthe context that this timer is to be associated with
[in]periodthe duration between calls to the callback in nanoseconds
[in]callbackthe user defined function to be called every period
[in]allocatorthe allocator to use for allocations
Returns
RCL_RET_OK if the timer was initialized successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_ALREADY_INIT if the timer was already initialized, or
RCL_RET_BAD_ALLOC if allocating memory failed, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_fini()

rcl_ret_t rcl_timer_fini ( rcl_timer_t timer)

Finalize a timer.

This function will deallocate any memory and make the timer invalid.

A timer that is already invalid (zero initialized) or NULL will not fail.

This function is not thread-safe with any rcl_timer_* functions used on the same timer object.


Attribute Adherence
Allocates Memory Yes
Thread-Safe No
Uses Atomics Yes
Lock-Free Yes [1][2][3]

[1] if atomic_is_lock_free() returns true for atomic_uintptr_t

[2] if atomic_is_lock_free() returns true for atomic_uint_least64_t

[3] if atomic_is_lock_free() returns true for atomic_bool

Parameters
[in,out]timerthe handle to the timer to be finalized.
Returns
RCL_RET_OK if the timer was finalized successfully, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_call()

rcl_ret_t rcl_timer_call ( rcl_timer_t timer)

Call the timer's callback and set the last call time.

This function will call the callback and change the last call time even if the timer's period has not yet elapsed. It is up to the calling code to make sure the period has elapsed by first calling rcl_timer_is_ready(). If the callback pointer is NULL (either set in init or exchanged after initialized), no callback is fired. However, this function should still be called by the client library to update the state of the timer. The order of operations in this command are as follows:

  • Ensure the timer has not been canceled.
  • Get the current time into a temporary rcl_steady_time_point_t.
  • Exchange the current time with the last call time of the timer.
  • Call the callback, passing this timer and the time since the last call.
  • Return after the callback has completed.

During the callback the timer can be canceled or have its period and/or callback modified.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes [1]
Uses Atomics Yes
Lock-Free Yes [2]

[1] user callback might not be thread-safe

[2] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in,out]timerthe handle to the timer to call
Returns
RCL_RET_OK if the timer was called successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_TIMER_CANCELED if the timer has been canceled, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_clock()

rcl_ret_t rcl_timer_clock ( rcl_timer_t timer,
rcl_clock_t **  clock 
)

Retrieve the clock of the timer.

This function retrieves the clock pointer and copies it into the given variable.

The clock argument must be a pointer to an already allocated rcl_clock_t *.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics No
Lock-Free Yes
Parameters
[in]timerthe handle to the timer which is being queried
[out]clockthe rcl_clock_t * in which the clock is stored
Returns
RCL_RET_OK if the period was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_is_ready()

rcl_ret_t rcl_timer_is_ready ( const rcl_timer_t timer,
bool *  is_ready 
)

Calculates whether or not the timer should be called.

The result is true if the time until next call is less than, or equal to, 0 and the timer has not been canceled. Otherwise the result is false, indicating the timer should not be called.

The is_ready argument must point to an allocated bool object, as the result is copied into it.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerthe handle to the timer which is being checked
[out]is_readythe bool used to store the result of the calculation
Returns
RCL_RET_OK if the last call time was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_get_time_until_next_call()

rcl_ret_t rcl_timer_get_time_until_next_call ( const rcl_timer_t timer,
int64_t *  time_until_next_call 
)

Calculate and retrieve the time until the next call in nanoseconds.

This function calculates the time until the next call by adding the timer's period to the last call time and subtracting that sum from the current time. The calculated time until the next call can be positive, indicating that it is not ready to be called as the period has not elapsed since the last call. The calculated time until the next call can also be 0 or negative, indicating that the period has elapsed since the last call and the timer should be called. A negative value indicates the timer call is overdue by that amount.

The time_until_next_call argument must point to an allocated int64_t, as the time until is copied into that instance.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerthe handle to the timer that is being queried
[out]time_until_next_callthe output variable for the result
Returns
RCL_RET_OK if the timer until next call was successfully calculated, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_get_time_since_last_call()

rcl_ret_t rcl_timer_get_time_since_last_call ( const rcl_timer_t timer,
int64_t *  time_since_last_call 
)

Retrieve the time since the previous call to rcl_timer_call() occurred.

This function calculates the time since the last call and copies it into the given int64_t variable.

Calling this function within a callback will not return the time since the previous call but instead the time since the current callback was called.

The time_since_last_call argument must be a pointer to an already allocated int64_t.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerthe handle to the timer which is being queried
[out]time_since_last_callthe struct in which the time is stored
Returns
RCL_RET_OK if the last call time was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_get_period()

rcl_ret_t rcl_timer_get_period ( const rcl_timer_t timer,
int64_t *  period 
)

Retrieve the period of the timer.

This function retrieves the period and copies it into the given variable.

The period argument must be a pointer to an already allocated int64_t.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerthe handle to the timer which is being queried
[out]periodthe int64_t in which the period is stored
Returns
RCL_RET_OK if the period was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_exchange_period()

rcl_ret_t rcl_timer_exchange_period ( const rcl_timer_t timer,
int64_t  new_period,
int64_t *  old_period 
)

Exchange the period of the timer and return the previous period.

This function exchanges the period in the timer and copies the old one into the given variable.

Exchanging (changing) the period will not affect already waiting wait sets.

The old_period argument must be a pointer to an already allocated int64_t.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerthe handle to the timer which is being modified
[out]new_periodthe int64_t to exchange into the timer
[out]old_periodthe int64_t in which the previous period is stored
Returns
RCL_RET_OK if the period was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_get_callback()

rcl_timer_callback_t rcl_timer_get_callback ( const rcl_timer_t timer)

Return the current timer callback.

This function can fail, and therefore return NULL, if:

  • timer is NULL
  • timer has not been initialized (the implementation is invalid)

Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in]timerhandle to the timer from the callback should be returned
Returns
function pointer to the callback, or NULL if an error occurred

◆ rcl_timer_exchange_callback()

rcl_timer_callback_t rcl_timer_exchange_callback ( rcl_timer_t timer,
const rcl_timer_callback_t  new_callback 
)

Exchange the current timer callback and return the current callback.

This function can fail, and therefore return NULL, if:

  • timer is NULL
  • timer has not been initialized (the implementation is invalid)

This function can set callback to NULL, in which case the callback is ignored when rcl_timer_call is called.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in,out]timerhandle to the timer from the callback should be exchanged
[in]new_callbackthe callback to be exchanged into the timer
Returns
function pointer to the old callback, or NULL if an error occurred

◆ rcl_timer_cancel()

rcl_ret_t rcl_timer_cancel ( rcl_timer_t timer)

Cancel a timer.

When a timer is canceled, rcl_timer_is_ready() will return false for that timer, and rcl_timer_call() will fail with RCL_RET_TIMER_CANCELED.

A canceled timer can be reset with rcl_timer_reset(), and then used again. Calling this function on an already canceled timer will succeed.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in,out]timerthe timer to be canceled
Returns
RCL_RET_OK if the last call time was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_is_canceled()

rcl_ret_t rcl_timer_is_canceled ( const rcl_timer_t timer,
bool *  is_canceled 
)

Retrieve the canceled state of a timer.

If the timer is canceled true will be stored in the is_canceled argument. Otherwise false will be stored in the is_canceled argument.

The is_canceled argument must point to an allocated bool, as the result is copied into this variable.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_bool

Parameters
[in]timerthe timer to be queried
[out]is_canceledstorage for the is canceled bool
Returns
RCL_RET_OK if the last call time was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_reset()

rcl_ret_t rcl_timer_reset ( rcl_timer_t timer)

Reset a timer.

This function can be called on a timer, canceled or not. For all timers it will reset the last call time to now. For canceled timers it will additionally make the timer not canceled.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics Yes
Lock-Free Yes [1]

[1] if atomic_is_lock_free() returns true for atomic_int_least64_t

Parameters
[in,out]timerthe timer to be reset
Returns
RCL_RET_OK if the last call time was retrieved successfully, or
RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
RCL_RET_TIMER_INVALID if the timer is invalid, or
RCL_RET_ERROR an unspecified error occur.

◆ rcl_timer_get_allocator()

const rcl_allocator_t* rcl_timer_get_allocator ( const rcl_timer_t timer)

Return the allocator for the timer.

This function can fail, and therefore return NULL, if:

  • timer is NULL
  • timer has not been initialized (the implementation is invalid)

The returned pointer is only valid as long as the timer object is valid.


Attribute Adherence
Allocates Memory No
Thread-Safe Yes
Uses Atomics No
Lock-Free Yes
Parameters
[in,out]timerhandle to the timer object
Returns
pointer to the allocator, or NULL if an error occurred

◆ rcl_timer_get_guard_condition()

rcl_guard_condition_t* rcl_timer_get_guard_condition ( const rcl_timer_t timer)

Retrieve a guard condition used by the timer to wake the waitset when using ROSTime.


Attribute Adherence
Allocates Memory No
Thread-Safe No
Uses Atomics No
Lock-Free Yes
Parameters
[in]timerthe timer to be queried
Returns
NULL if the timer is invalid or does not have a guard condition, or
a guard condition pointer.