subscribers.rs
Overview
This file defines a Subscriber trait for handling thread lifecycle events related to blocks and threads within a concurrency or parallelism framework. It provides an abstraction for reacting to thread start and stop events via two key methods. Additionally, the file implements a macro to automatically generate Subscriber trait implementations for tuples of multiple Subscriber objects, enabling simultaneous notification of several subscribers.
The core purpose is to facilitate event-driven handling of thread operations by decoupling the event producer from the event consumers (subscribers). This allows multiple subscribers to be notified of thread lifecycle changes in a composable and scalable manner.
Trait: Subscriber
Description
The Subscriber trait defines an interface for receiving notifications when threads start and stop. It abstracts over any type capable of handling these events, enabling flexible subscriber implementations.
Methods
handle_start_thread
fn handle_start_thread(
&mut self,
parent_split_block: &BlockIdentifier,
thread_identifier: &ThreadIdentifier,
threads_table: Option<ThreadsTable>,
);
Parameters:
parent_split_block: Reference to aBlockIdentifierindicating the block that spawned (split) the new thread.thread_identifier: Reference to aThreadIdentifieruniquely identifying the newly started thread.threads_table: OptionalThreadsTablecontaining data about currently active threads or thread metadata.
Return value: None.
Purpose: This method is called to notify the subscriber that a new thread has started. Subscribers can use the provided identifiers and optional threads table to update internal state, log information, or trigger other processing.
Usage example:
impl Subscriber for Logger {
fn handle_start_thread(
&mut self,
parent_split_block: &BlockIdentifier,
thread_identifier: &ThreadIdentifier,
threads_table: Option<ThreadsTable>,
) {
// Log the start of a thread
self.log(format!("Thread {:?} started from block {:?}", thread_identifier, parent_split_block));
}
// ...
}
handle_stop_thread
fn handle_stop_thread(
&mut self,
last_thread_block: &BlockIdentifier,
thread_identifier: &ThreadIdentifier,
);
Parameters:
last_thread_block: Reference to aBlockIdentifierindicating the block where the thread stopped or completed.thread_identifier: Reference to aThreadIdentifieruniquely identifying the thread that stopped.
Return value: None.
Purpose: This method is called to notify the subscriber that a thread has stopped. Subscribers can use this information to update tracking data, release resources, or perform cleanup.
Usage example:
impl Subscriber for Logger {
fn handle_stop_thread(
&mut self,
last_thread_block: &BlockIdentifier,
thread_identifier: &ThreadIdentifier,
) {
// Log the stop of a thread
self.log(format!("Thread {:?} stopped at block {:?}", thread_identifier, last_thread_block));
}
}
Macro: tuple_subs!
Description
The macro tuple_subs! provides a convenient way to implement the Subscriber trait for tuple types containing multiple mutable references to subscriber instances. This allows a single call to a subscriber tuple to broadcast events to all contained subscribers.
The macro accepts pairs of tuple indices and generic type identifiers, generating an implementation of Subscriber for tuples up to 5 elements in size (as instantiated below the macro). Each subscriber in the tuple receives the same event notifications with cloned threads_table where applicable.
Generated Implementation Details
For each tuple element, the macro calls the corresponding subscriber's
handle_start_threadandhandle_stop_threadmethods.The
threads_tableparameter is cloned for each subscriber to avoid ownership conflicts since it's anOption<ThreadsTable>.The macro supports tuples of sizes from 1 to 5 by default, but can be extended for larger tuples if needed.
Instantiations in this file
tuple_subs!(0 A);
tuple_subs!(0 A, 1 B);
tuple_subs!(0 A, 1 B, 2 C);
tuple_subs!(0 A, 1 B, 2 C, 3 D);
tuple_subs!(0 A, 1 B, 2 C, 3 D, 4 E);
These lines create Subscriber implementations for tuples with 1 to 5 mutable subscribers.
Usage example
let mut subscriber1 = Logger::new();
let mut subscriber2 = MetricsCollector::new();
let mut combined_subscribers = (&mut subscriber1, &mut subscriber2);
combined_subscribers.handle_start_thread(&block_id, &thread_id, Some(threads_table));
combined_subscribers.handle_stop_thread(&block_id, &thread_id);
In this example, both subscriber1 and subscriber2 receive the thread lifecycle events via the tuple implementation.
Important Implementation Details
The use of a macro to support tuples avoids boilerplate code while enabling flexible composition of subscribers.
The cloning of
threads_tableinhandle_start_threadcalls ensures each subscriber can independently consume or modify the data without affecting others.The file relies on external types
BlockIdentifier,ThreadIdentifier, andThreadsTablefrom thetypesmodule, which represent abstractions related to blocks of execution and thread metadata. These types are critical to understanding the parameters passed to subscriber methods.
Interaction with Other Parts of the System
The
Subscribertrait is intended to be implemented by components that react to thread lifecycle events, such as logging, profiling, debugging, metrics collection, or synchronization mechanisms.It interacts with the concurrency management system that generates thread events, which calls
handle_start_threadandhandle_stop_threadto notify subscribers.The
BlockIdentifier,ThreadIdentifier, andThreadsTabletypes used in the method signatures are defined elsewhere (likely in atypesmodule), and are essential for identifying and describing thread execution contexts.The macro-generated tuple implementations allow multiple subscribers to be registered and notified together, facilitating modularity and extensibility.
Structure Diagram
classDiagram
class Subscriber {
<<trait>>
+handle_start_thread()
+handle_stop_thread()
}
class tuple_subs {
<<macro>>
}
Subscriber <|.. tuple_subs
This diagram shows:
The
Subscribertrait with its two primary methods.The
tuple_subsmacro which generates implementations of theSubscribertrait for tuples containing multiple subscriber instances.