@web-font-path: "roboto-debian.css";
v2.2.0 (RP2040)
Loading...
Searching...
No Matches
pico_async_context

An async_context provides a logically single-threaded context for performing work, and responding to asynchronous events. Thus an async_context instance is suitable for servicing third-party libraries that are not re-entrant. More...

## Topics

| async_context_freertos
| async_context_freertos provides an implementation of async_context that handles asynchronous work in a separate FreeRTOS task.
| async_context_poll
| async_context_poll provides an implementation of async_context that is intended for use with a simple polling loop on one core. It is not thread safe.
| async_context_threadsafe_background
| async_context_threadsafe_background provides an implementation of async_context that handles asynchronous work in a low priority IRQ, and there is no need for the user to poll for work

## Data Structures

struct | async_work_on_timeout
| A "timeout" instance used by an async_context. More...
struct | async_when_pending_worker
| A "worker" instance used by an async_context. More...
struct | async_context_type
| Implementation of an async_context type, providing methods common to that type. More...
struct | async_context
| Base structure type of all async_contexts. For details about its use, see pico_async_context. More...

## Typedefs

typedef struct async_work_on_timeout | async_at_time_worker_t
| A "timeout" instance used by an async_context.
typedef struct async_when_pending_worker | async_when_pending_worker_t
| A "worker" instance used by an async_context.
typedef struct async_context_type | async_context_type_t
| Implementation of an async_context type, providing methods common to that type.

## Functions

static void | async_context_acquire_lock_blocking (async_context_t *context)
| Acquire the async_context lock.
static void | async_context_release_lock (async_context_t *context)
| Release the async_context lock.
static void | async_context_lock_check (async_context_t *context)
| Assert if the caller does not own the lock for the async_context.
static uint32_t | async_context_execute_sync (async_context_t *context, uint32_t(*func)(void *param), void *param)
| Execute work synchronously on the core the async_context belongs to.
static bool | async_context_add_at_time_worker (async_context_t *context, async_at_time_worker_t *worker)
| Add an "at time" worker to a context.
static bool | async_context_add_at_time_worker_at (async_context_t *context, async_at_time_worker_t *worker, absolute_time_t at)
| Add an "at time" worker to a context.
static bool | async_context_add_at_time_worker_in_ms (async_context_t *context, async_at_time_worker_t *worker, uint32_t ms)
| Add an "at time" worker to a context.
static bool | async_context_remove_at_time_worker (async_context_t *context, async_at_time_worker_t *worker)
| Remove an "at time" worker from a context.
static bool | async_context_add_when_pending_worker (async_context_t *context, async_when_pending_worker_t *worker)
| Add a "when pending" worker to a context.
static bool | async_context_remove_when_pending_worker (async_context_t *context, async_when_pending_worker_t *worker)
| Remove a "when pending" worker from a context.
static void | async_context_set_work_pending (async_context_t *context, async_when_pending_worker_t *worker)
| Mark a "when pending" worker as having work pending.
static void | async_context_poll (async_context_t *context)
| Perform any pending work for polling style async_context.
static void | async_context_wait_until (async_context_t *context, absolute_time_t until)
| sleep until the specified time in an async_context callback safe way
static void | async_context_wait_for_work_until (async_context_t *context, absolute_time_t until)
| Block until work needs to be done or the specified time has been reached.
static void | async_context_wait_for_work_ms (async_context_t *context, uint32_t ms)
| Block until work needs to be done or the specified number of milliseconds have passed.
static uint | async_context_core_num (const async_context_t *context)
| Return the processor core this async_context belongs to.
static void | async_context_deinit (async_context_t *context)
| End async_context processing, and free any resources.

## Detailed Description

An async_context provides a logically single-threaded context for performing work, and responding to asynchronous events. Thus an async_context instance is suitable for servicing third-party libraries that are not re-entrant.

The "context" in async_context refers to the fact that when calling workers or timeouts within the async_context various pre-conditions hold:

1. That there is a single logical thread of execution; i.e. that the context does not call any worker functions concurrently.
2. That the context always calls workers from the same processor core, as most uses of async_context rely on interaction with IRQs which are themselves core-specific.

THe async_context provides two mechanisms for asynchronous work:

- when_pending workers, which are processed whenever they have work pending. See async_context_add_when_pending_worker, async_context_remove_when_pending_worker, and async_context_set_work_pending, the latter of which can be used from an interrupt handler to signal that servicing work is required to be performed by the worker from the regular async_context.
- at_time workers, that are executed after at a specific time.

Note: "when pending" workers with work pending are executed before "at time" workers.

The async_context provides locking mechanisms, see async_context_acquire_lock_blocking, async_context_release_lock and async_context_lock_check which can be used by external code to ensure execution of external code does not happen concurrently with worker code. Locked code runs on the calling core, however async_context_execute_sync is provided to synchronously run a function from the core of the async_context.

The SDK ships with the following default async_contexts:

async_context_poll - this context is not thread-safe, and the user is responsible for calling async_context_poll() periodically, and can use async_context_wait_for_work_until() to sleep between calls until work is needed if the user has nothing else to do.

async_context_threadsafe_background - in order to work in the background, a low priority IRQ is used to handle callbacks. Code is usually invoked from this IRQ context, but may be invoked after any other code that uses the async context in another (non-IRQ) context on the same core. Calling async_context_poll() is not required, and is a no-op. This context implements async_context locking and is thus safe to call from either core, according to the specific notes on each API.

async_context_freertos - Work is performed from a separate "async_context" task, however once again, code may also be invoked after a direct use of the async_context on the same core that the async_context belongs to. Calling async_context_poll() is not required, and is a no-op. This context implements async_context locking and is thus safe to call from any task, and from either core, according to the specific notes on each API.

Each async_context provides bespoke methods of instantiation which are provided in the corresponding headers (e.g. async_context_poll.h, async_context_threadsafe_background.h, asycn_context_freertos.h). async_contexts are de-initialized by the common async_context_deint() method.

Multiple async_context instances can be used by a single application, and they will operate independently.

## Typedef Documentation

## async_at_time_worker_t

typedef struct async_work_on_timeout async_at_time_worker_t

A "timeout" instance used by an async_context.

A "timeout" represents some future action that must be taken at a specific time. Its methods are called from the async_context under lock at the given time

See also
  async_context_add_at_time_worker_at
  async_context_add_at_time_worker_in_ms

## async_when_pending_worker_t

typedef struct async_when_pending_worker async_when_pending_worker_t

A "worker" instance used by an async_context.

A "worker" represents some external entity that must do work in response to some external stimulus (usually an IRQ). Its methods are called from the async_context under lock at the given time

See also
  async_context_add_at_time_worker_at
  async_context_add_at_time_worker_in_ms

## Function Documentation

## async_context_acquire_lock_blocking()

void async_context_acquire_lock_blocking | ( | async_context_t * | context | ) |

inline static

Acquire the async_context lock.

The owner of the async_context lock is the logic owner of the async_context and other work related to this async_context will not happen concurrently.

This method may be called in a nested fashion by the the lock owner.

Note
  the async_context lock is nestable by the same caller, so an internal count is maintained
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context

See also
  async_context_release_lock

## async_context_add_at_time_worker()

bool async_context_add_at_time_worker | ( | async_context_t * | context,
|  | async_at_time_worker_t * | worker )

inline static

Add an "at time" worker to a context.

An "at time" worker will run at or after a specific point in time, and is automatically when (just before) it runs.

The time to fire is specified in the next_time field of the worker.

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "at time" worker to add

Returns
  true if the worker was added, false if the worker was already present.

## async_context_add_at_time_worker_at()

bool async_context_add_at_time_worker_at | ( | async_context_t * | context,
|  | async_at_time_worker_t * | worker,
|  | absolute_time_t | at )

inline static

Add an "at time" worker to a context.

An "at time" worker will run at or after a specific point in time, and is automatically when (just before) it runs.

The time to fire is specified by the at parameter.

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "at time" worker to add
  at | the time to fire at

Returns
  true if the worker was added, false if the worker was already present.

## async_context_add_at_time_worker_in_ms()

bool async_context_add_at_time_worker_in_ms | ( | async_context_t * | context,
|  | async_at_time_worker_t * | worker,
|  | uint32_t | ms )

inline static

Add an "at time" worker to a context.

An "at time" worker will run at or after a specific point in time, and is automatically when (just before) it runs.

The time to fire is specified by a delay via the ms parameter

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "at time" worker to add
  ms | the number of milliseconds from now to fire after

Returns
  true if the worker was added, false if the worker was already present.

## async_context_add_when_pending_worker()

bool async_context_add_when_pending_worker | ( | async_context_t * | context,
|  | async_when_pending_worker_t * | worker )

inline static

Add a "when pending" worker to a context.

An "when pending" worker will run when it is pending (can be set via async_context_set_work_pending), and is NOT automatically removed when it runs.

The time to fire is specified by a delay via the ms parameter

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "when pending" worker to add

Returns
  true if the worker was added, false if the worker was already present.

## async_context_core_num()

uint async_context_core_num | ( | const async_context_t * | context | ) |

inline static

Return the processor core this async_context belongs to.

Parameters

  context | the async_context

Returns
  the physical core number

## async_context_deinit()

void async_context_deinit | ( | async_context_t * | context | ) |

inline static

End async_context processing, and free any resources.

Note the user should clean up any resources associated with workers in the async_context themselves.

Asynchronous (non-polled) async_contexts guarantee that no callback is being called once this method returns.

Parameters

  context | the async_context

## async_context_execute_sync()

uint32_t async_context_execute_sync | ( | async_context_t * | context,
|  | uint32_t(* | func )(void *param),
|  | void * | param )

inline static

Execute work synchronously on the core the async_context belongs to.

This method is intended for code external to the async_context (e.g. another thread/task) to execute a function with the same guarantees (single core, logical thread of execution) that async_context workers are called with.

Note
  you should NOT call this method while holding the async_context's lock

Parameters

  context | the async_context
  func | the function to call
  param | the parameter to pass to the function

Returns
  the return value from func

## async_context_lock_check()

void async_context_lock_check | ( | async_context_t * | context | ) |

inline static

Assert if the caller does not own the lock for the async_context.

Note
  this method is thread-safe

Parameters

  context | the async_context

## async_context_poll()

void async_context_poll | ( | async_context_t * | context | ) |

inline static

Perform any pending work for polling style async_context.

For a polled async_context (e.g. async_context_poll) the user is responsible for calling this method periodically to perform any required work.

This method may immediately perform outstanding work on other context types, but is not required to.

Parameters

  context | the async_context

## async_context_release_lock()

void async_context_release_lock | ( | async_context_t * | context | ) |

inline static

Release the async_context lock.

Note
  the async_context lock may be called in a nested fashion, so an internal count is maintained. On the outermost release, When the outermost lock is released, a check is made for work which might have been skipped while the lock was held, and any such work may be performed during this call IF the call is made from the same core that the async_context belongs to.
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context

See also
  async_context_acquire_lock_blocking

## async_context_remove_at_time_worker()

bool async_context_remove_at_time_worker | ( | async_context_t * | context,
|  | async_at_time_worker_t * | worker )

inline static

Remove an "at time" worker from a context.

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "at time" worker to remove

Returns
  true if the worker was removed, false if the instance not present.

## async_context_remove_when_pending_worker()

bool async_context_remove_when_pending_worker | ( | async_context_t * | context,
|  | async_when_pending_worker_t * | worker )

inline static

Remove a "when pending" worker from a context.

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  worker | the "when pending" worker to remove

Returns
  true if the worker was removed, false if the instance not present.

## async_context_set_work_pending()

void async_context_set_work_pending | ( | async_context_t * | context,
|  | async_when_pending_worker_t * | worker )

inline static

Mark a "when pending" worker as having work pending.

The worker will be run from the async_context at a later time.

Note
  this method may be called from any context including IRQs

Parameters

  context | the async_context
  worker | the "when pending" worker to mark as pending.

## async_context_wait_for_work_ms()

void async_context_wait_for_work_ms | ( | async_context_t * | context,
|  | uint32_t | ms )

inline static

Block until work needs to be done or the specified number of milliseconds have passed.

Note
  this method should not be called from a worker callback

Parameters

  context | the async_context
  ms | the number of milliseconds to return after if no work is required

## async_context_wait_for_work_until()

void async_context_wait_for_work_until | ( | async_context_t * | context,
|  | absolute_time_t | until )

inline static

Block until work needs to be done or the specified time has been reached.

Note
  this method should not be called from a worker callback

Parameters

  context | the async_context
  until | the time to return at if no work is required

## async_context_wait_until()

void async_context_wait_until | ( | async_context_t * | context,
|  | absolute_time_t | until )

inline static

sleep until the specified time in an async_context callback safe way

Note
  for async_contexts that provide locking (not async_context_poll), this method is threadsafe. and may be called from within any worker method called by the async_context or from any other non-IRQ context.

Parameters

  context | the async_context
  until | the time to sleep until