Skip to content

Wait set groups #308

@sloretz

Description

@sloretz

Feature request

This is a request for an API on top of the current waitset api that considers groups of waitable entities.

Feature description

An API that covers groups of entities that can be waited on would be immediately useful for actions. A server and client consists of several waitable entities (servers, clients, maybe a timer). The API would allow a client library to add a group of waitable entities to the wait set, and then notify the action server when one of them becomes available.

Implementation considerations

This could be implemented in a package rcl_grouped_waitset on top of the existing rcl API

Structs and methods to be added.

struct rcl_grouped_waitset
{
  rcl_waitset_group_t * groups;
  size_t num_groups;

  rcl_waitset_group_impl_t * impl;
}

struct rcl_waitset_group_t
{
  rcl_subscription_t * subscriptions;
  rcl_guard_condition_t * guard_conditions;
  rcl_timer_t * timers;
  rcl_client_t * clients;
  rcl_service_t * servers;

  size_t num_subscriptions;
  size_t num_guard_conditions;
  size_t num_timers;
  size_t num_clients;
  size_t num_servers;
}
rcl_waitset_group_get_zero_initialized();

// User won't call these, but rcl_grouped_waitset_add and rcl_grouped_waitset_fini might
// rcl_waitset_group_init(rcl_waitset_group_t *, num_subs, subs, ..., rcl_allocator_t alloc);
// rcl_waitset_group_fini(rcl_waitset_group_t * g);

rcl_grouped_waitset_get_zero_initialized();
rcl_grouped_waitset_init(rcl_grouped_waitset_t * gws, size_t num_groups, rcl_allocator_t alloc);
rcl_grouped_waitset_fini(rcl_grouped_waitset_t * gws);

// Add a group waitable entities to the wait set
// This returns a waitset group that can be used to tell which entities in the group woke the wait set
// The returned group isn't usable until `rcl_grouped_waitset_build()` is called. The returned group never needs to be cleaned up by the user.
// subs, gcs, timers, etc pointers are borrowed and must be valid until `rcl_grouped_waitset_build()` is called
rcl_grouped_waitset_add(rcl_grouped_waitset_t * gws, rcl_waitset_group_t * g, size_t num_subs, rcl_subscription_t * subs, size_t num_guard_conditions, , rcl_guard_condition_t * gcs, size_t num_timers, rcl_timer_t * timers, size_t num_clients, rcl_client_t * clients, size_t num_servers, rcl_server_t * servers);

// Called after all groups have been added so allocation of the wait set only happens once
rcl_grouped_waitset_build();

// Calls `rcl_wait(rcl_waitset_t ws,...)` internally using a waitset built in `_build()` and stored in the implementation of the group object.
rcl_grouped_wait(rcl_grouped_waitset_t * gws, int64_t timeout);

Example use

rcl_waitset_group_t gws = rcl_grouped_waitset_get_zero_initialized();
rcl_grouped_waitset_init(&gws, num_groups, alloc);

// Client library builds a group with all of the users subs, clients, services, timers, etc
rcl_waitset_group_t cl_group = rcl_waitset_group_get_zero_initialized();
rcl_grouped_waitset_add(&gws, &cl_group, ...);

// For each action server client library asks it to add itself to the waitset group
{
  rcl_waitset_group group = rcl_waitset_group_get_zero_initialized();
  // This calls rcl_grouped_waitset_add() internally
  rcl_action_server_add_to_grouped_waitset(&as, &gws, &group);
}

rcl_grouped_wait(gws, ...)

// Entities are set to NULL within the added groups
for (size_t g = 0; g < gws.num_groups; ++g)
{
  const rcl_waitset_group_t * group = gws.groups[g];
  for (size_t s = 0; s < group->num_subscriptions; ++s)
  {
    // client library does right thing
    // First group could be user defined stuff,
    // Following groups could be for action servers, action clients, etc
  }
}

// When done finalizing the grouped waitset also cleans up the groups
// This works because rcl_grouped_waitset_build() set the pointers to the entities to be internal to an `rcl_waitset_t1
rcl_grouped_waitset_fini(gws);

connects to #307

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions