Conversation
This is something that needs to be done before v1 so we can have some backward compatibility And we needed cl_id and task_id in a bunch of contexts.
It is everywhere, it needs to be a little bit terse
There was a problem hiding this comment.
Pull request overview
This PR introduces CuContext as an extensible execution context to replace RobotClock in all task and bridge callbacks. This change provides tasks with access to the robot clock, copper list ID (cl_id), and task metadata (task_id), establishing a foundation for adding future context fields without breaking API compatibility.
Changes:
- Introduced
CuContextstruct with builder pattern, providing clock access viaDeref<Target = RobotClock>, cl_id, and task metadata - Updated all task trait signatures (
CuTask,CuSrcTask,CuSinkTask) and bridge trait signatures (CuBridge) to accept&CuContextinstead of&RobotClock - Modified code generation in
cu29_deriveto create and manageCuContextinstances and set current task context before callbacks - Updated 60+ example files and all component implementations (sources, sinks, tasks, bridges) to use the new signature
Reviewed changes
Copilot reviewed 92 out of 92 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| core/cu29_runtime/src/context.rs | New CuContext type with clock, cl_id, and task metadata; implements Deref for backward compatibility |
| core/cu29_runtime/src/cutask.rs | Updated trait signatures for CuTask, CuSrcTask, CuSinkTask to use &CuContext |
| core/cu29_runtime/src/cubridge.rs | Updated CuBridge trait signatures to use &CuContext |
| core/cu29_derive/src/lib.rs | Code generation updates to create CuContext and manage task context |
| core/cu29_runtime/src/cuasynctask.rs | Async task wrapper updated to pass CuContext |
| core/cu29_runtime/src/simulation.rs | Simulation support updated for new signatures |
| core/cu29/src/lib.rs | Export context module in prelude |
| examples/* (60+ files) | All example tasks updated to use &CuContext parameter |
| components/* (35+ files) | All components (sources, sinks, bridges) updated to use &CuContext |
Comments suppressed due to low confidence (5)
components/bridges/cu_zenoh_bridge/src/lib.rs:336
- Variable name shadowing: the parameter
_ctx(aCuContext) shadows the local variablectx(aZenohContext). This creates confusion and could lead to bugs where the wrong context is referenced. Consider renaming the local variable toruntime_ctxorzenoh_ctxfor clarity, similar to how it was done in thereceivemethod (line 365) and in the ROS2 bridge.
fn send<'a, Payload>(
&mut self,
_ctx: &CuContext,
channel: &'static BridgeChannel<<Self::Tx as BridgeChannelSet>::Id, Payload>,
msg: &CuMsg<Payload>,
) -> CuResult<()>
where
Payload: CuMsgPayload + 'a,
{
let ctx = self
.ctx
.as_mut()
.ok_or_else(|| CuError::from("ZenohBridge: Context not initialized"))?;
examples/cu_monitoring/src/main.rs:117
- Inconsistent API: The
CuMonitortrait methodsstartandstopstill use&RobotClockinstead of&CuContext, which is inconsistent with the changes made toCuTask,CuSrcTask,CuSinkTask, andCuBridgetraits. This inconsistency means that monitor callbacks cannot accesscl_id()ortask_id()like other callbacks can. For API consistency and to meet the PR's goal of providing context to all callbacks, these methods should also be updated to use&CuContext.
components/bridges/cu_iceoryx2_bridge/src/lib.rs:489 - Variable name shadowing: the parameter
_ctx(aCuContext) shadows the local variablectx(anIceoryxContext). This creates confusion and could lead to bugs where the wrong context is referenced. Consider renaming the local variable toruntime_ctxoriceoryx_ctxfor clarity, similar to how it was done in thereceivemethod at line 545.
fn start(&mut self, _ctx: &CuContext) -> CuResult<()> {
let mut builder = NodeBuilder::new();
if let Some(name) = &self.node_name {
builder = builder.name(name);
}
let node = builder
.create::<IceoryxService>()
.map_err(|e| CuError::new_with_cause("Iceoryx2Bridge: Failed to create node", e))?;
let ctx = IceoryxContext::<Tx::Id, Rx::Id> {
node,
tx_channels: Vec::new(),
rx_channels: Vec::new(),
};
self.ctx = Some(Box::new(RuntimeContext::new(ctx)));
Ok(())
components/bridges/cu_iceoryx2_bridge/src/lib.rs:525
- Variable name shadowing: the parameter
_ctx(aCuContext) shadows the local variablectx(returned fromself.ctx_mut()). This creates confusion and could lead to bugs where the wrong context is referenced. Consider renaming the local variable toruntime_ctxoriceoryx_ctxfor clarity, similar to how it was done in thereceivemethod at line 545.
fn send<'a, Payload>(
&mut self,
_ctx: &CuContext,
channel: &'static BridgeChannel<<Self::Tx as BridgeChannelSet>::Id, Payload>,
msg: &CuMsg<Payload>,
) -> CuResult<()>
where
Payload: CuMsgPayload + 'a + 'static,
{
let cfg = self.find_tx_config(channel.id()).ok_or_else(|| {
CuError::from(format!(
"Iceoryx2Bridge: Unknown Tx channel {:?}",
channel.id()
))
})?;
let service = cfg.service.clone();
let max_payload_bytes = cfg.max_payload_bytes;
let ctx = self.ctx_mut()?;
if let Some(tx_channel) =
Self::find_tx_channel_mut::<Payload>(&mut ctx.tx_channels, channel.id())?
{
return tx_channel.send(msg);
}
let mut new_channel =
IceoryxTxChannel::<Payload>::new(&mut ctx.node, &service, max_payload_bytes)?;
new_channel.send(msg)?;
ctx.tx_channels.push(IceoryxTxChannelEntry {
id: channel.id(),
channel: Box::new(new_channel),
});
Ok(())
components/sources/cu_rp_encoder/src/lib.rs:145
- Unnecessary full context clone: The code clones the entire
CuContext(which includes task_ids and other fields) just to access the clock in the interrupt handler. Since the interrupt handler only needs time access viaclock.now(), consider cloning just the clock field instead:let clock = ctx.clock.clone();. This is more efficient and makes the intent clearer.
let clock = ctx.clone();
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@codex review. and specifically focus on ctx parameter |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 207d570519
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
makeecat
left a comment
There was a problem hiding this comment.
Agree with codex review.
This is a potential ambiguity in CuContext::cl_id() lifecycle
CuContext is documented as providing the “current copper-list id”, but generated runtime code passes a context without cl_id set during some callbacks (preprocess,start, stop). In those paths, cl_id is still the default 0, which can be misread as a real CL id.
We can potentially do either of these two options:
- Clarify docs/contracts that
cl_idis only valid during per-copperlist execution callbacks. - Make absence explicit in API (e.g.,
cl_id() -> Option<u64>orhas_cl_id()), instead of overloading0.
|
@makeecat fair enough. It is cleaner to change the semantics a little bit to: this start / stop / preprocess / postprocess where it would be this CL id evn if at the time of the call it might not exist in memory. pushed a fix, it is cheap too. |
Summary
This is something that needs to be done before v1 so we can have some backward compatibility headroom (ie so we can add features to the callbacks without breaking them)
And we needed cl_id (copper list seq id) and task_id (numerical and string) in a bunch of use cases where the user wants to know what is ... the context.. of this execution. For example, which camera is it from (task_id), what is the image sequence number (cl_id).
Also added it to the monitor callbacks and UI:

Related issues
Changes
Testing
just fmtjust lintjust testjust std-ci(if std/runtime paths are impacted)just nostd-ci(if embedded/no_std paths are impacted)pro-tip:
justwith no parameters in the root defaults tojust fmt,just lint, andjust test.Checklist
Breaking changes (if any)
major: all the copper tasks in the world but this is to minimize future breakages.
Additional context