Built-in Extensions¶
NUClear ships with four extension reactors that provide core system services.
These are ordinary reactors — they use the same on<>() DSL as user code — but they implement the functionality that other DSL words depend on (timers, IO polling, networking, tracing).
Manual Installation Required
You must explicitly install them into the PowerPlant before using DSL words that depend on them:
NUClear::Configuration config;
config.default_pool_concurrency = 4;
NUClear::PowerPlant plant(config);
plant.install<NUClear::extension::ChronoController>(); // Required for Every, Watchdog, Delay
plant.install<NUClear::extension::IOController>(); // Required for IO
plant.install<NUClear::extension::NetworkController>(); // Required for Network
plant.install<NUClear::extension::TraceController>(); // Required for tracing
plant.install<MyReactor>();
plant.start();
flowchart TB
subgraph PP["PowerPlant"]
subgraph Chrono["ChronoController"]
CT["Priority queue of ChronoTasks"]
CV["Condition variable + nanosleep"]
end
subgraph IO["IOController"]
Poll["poll / WSAWaitForMultipleEvents"]
FD["File descriptor registry"]
end
subgraph Net["NetworkController"]
NN["NUClearNetwork"]
Peers["Peer discovery"]
Sock["Network sockets"]
end
subgraph Trace["TraceController"]
TF["Trace file (protobuf)"]
TT["Task timing records"]
end
end
Every & Watchdog & Delay -->|"register tasks"| Chrono
IOWord["IO"] -->|"register fds"| IO
NetworkListen & NetworkEmit -->|"register handlers"| Net
ReactionTask -->|"start/end events"| Trace
ChronoController¶
Manages all time-based operations in NUClear.
Handles:
Every— periodic reactions that fire at fixed intervalsWatchdog— timeout reactions that fire if not serviced within a deadlineDelay— deferred emissions that occur after a specified duration
Implementation:
The controller maintains a sorted priority queue of ChronoTask items, each with a target fire time and a callback.
A dedicated thread sleeps until the next task is due, using a combination of condition variable waits (for coarse timing) and nanosleep (for fine timing accuracy).
When a time-based word's bind is called, it submits a ChronoTask to this controller.
The task's callback typically re-submits itself (for Every) or triggers a reaction (for Watchdog expiry).
Key internals:
| Component | Purpose |
|---|---|
std::vector<ChronoTask> |
Tasks sorted by next fire time |
std::condition_variable |
Wakes the timing thread when tasks change |
cv_accuracy |
Measured accuracy of condition variable waits |
ns_accuracy |
Measured accuracy of nanosleep calls |
The controller also responds to TimeTravel messages, which shift the clock and re-evaluate all pending tasks.
IOController¶
Monitors file descriptors for IO readiness events and triggers corresponding reactions.
Handles:
IO— reactions that fire when a file descriptor becomes readable, writable, or errors
Implementation:
Uses platform-native polling mechanisms:
- POSIX (Linux/macOS):
poll()withpollfdarrays - Windows:
WSAWaitForMultipleEventswithWSAEVENThandles
A dedicated thread blocks on the polling call.
When events are detected on registered file descriptors, the controller creates tasks for the corresponding reactions, passing the event flags through ThreadStore so the get method can report which specific events occurred.
Key internals:
| Component | Purpose |
|---|---|
tasks_t |
Registry of fd → reaction mappings |
notifier_t |
Pipe/event used to wake the poll thread when registrations change |
listening_events |
What the task is waiting for |
waiting_events |
Events ready to fire |
processing_events |
Events currently being handled |
The controller coalesces multiple reactions on the same fd into a single poll entry and dispatches events to the correct reactions based on their registered interest masks.
NetworkController¶
Bridges the low-level NUClearNetwork protocol into NUClear's reaction system.
Handles:
NetworkConfiguration— configures the network name, multicast group, and portNetworkListen— registers reactions for incoming network messages by type hashNetworkEmit— sends serialized data to network peers
Implementation:
Wraps a NUClearNetwork instance that implements peer discovery (via multicast announcements) and reliable/unreliable message delivery.
The controller:
- Listens for
NetworkConfigurationmessages to initialize/reconfigure the network - Registers
IOreactions on network sockets so incoming data triggers processing - Maintains a map of type hashes to reactions for dispatching received messages
- Provides callbacks for peer join/leave events that emit
NetworkPeermessages
Key internals:
| Component | Purpose |
|---|---|
NUClearNetwork network |
Low-level networking (discovery, serialization, transport) |
std::multimap<uint64_t, Reaction> |
Type hash → interested reactions |
listen_handles |
IO reactions watching network sockets |
process_handle |
Reaction for timed network maintenance tasks |
TraceController¶
Records task execution traces for performance profiling and debugging.
Handles:
- Task start/end events from the threading system
- Thread identification and naming
- Trace file output in protobuf format (compatible with Perfetto)
Implementation:
Listens for task lifecycle events and writes trace records to a file. Each record captures the reaction identity, start/end timestamps, and which thread the task ran on. The output uses a protobuf wire format compatible with the Perfetto trace viewer.
Key internals:
| Component | Purpose |
|---|---|
TracePool |
Dedicated single-thread pool (persistent, non-idle-counting) |
StringInterner |
Deduplicates reaction/thread name strings in the trace file |
write_trace_packet() |
Serializes and writes individual trace events |
| Process/thread track IDs | Unique identifiers for the trace hierarchy |
The trace pool is marked persistent = true so it continues recording events even during shutdown, capturing the full lifecycle of the system.