pub trait ThreadFn {
// Required methods
fn is_null(&self) -> bool;
fn spawn<F>(
&mut self,
param: Option<ThreadParam>,
callback: F,
) -> Result<Self>
where F: Fn(Box<dyn Thread>, Option<ThreadParam>) -> Result<ThreadParam> + Send + Sync + 'static,
Self: Sized;
fn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
where F: Fn() -> Result<ThreadParam> + Send + Sync + 'static,
Self: Sized;
fn delete(&self);
fn suspend(&self);
fn resume(&self);
fn join(&self, retval: DoublePtr) -> Result<i32>;
fn get_metadata(&self) -> ThreadMetadata;
fn get_current() -> Self
where Self: Sized;
fn notify(&self, notification: ThreadNotification) -> Result<()>;
fn notify_from_isr(
&self,
notification: ThreadNotification,
higher_priority_task_woken: &mut BaseType,
) -> Result<()>;
fn wait_notification(
&self,
bits_to_clear_on_entry: u32,
bits_to_clear_on_exit: u32,
timeout_ticks: TickType,
) -> Result<u32>;
}Expand description
All OSAL trait definitions for advanced usage. Core thread/task trait.
Provides methods for thread lifecycle management, synchronization, and communication through task notifications.
§Thread Creation
Threads are typically created with Thread::new() specifying name,
stack size, and priority, then started with spawn() or spawn_simple().
§Thread Safety
All methods are thread-safe. ISR-specific methods (suffixed with _from_isr)
should only be called from interrupt context.
§Resource Management
Threads should be properly deleted with delete() when no longer needed
to free stack memory and control structures.
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
static WORK: AtomicU32 = AtomicU32::new(0);
// Create and spawn a simple thread
let mut thread = Thread::new("worker", 2048, 5);
let worker = thread.spawn_simple(|| {
for _ in 0..3 {
WORK.fetch_add(1, Ordering::SeqCst);
System::delay(5);
}
Ok(Arc::new(()))
}).unwrap();
// Create thread with parameter
let mut thread2 = Thread::new("counter", 1024, 5);
let counter: ThreadParam = Arc::new(AtomicU32::new(0));
let counting = thread2.spawn(Some(counter.clone()), |_thread, param| {
let param = param.unwrap();
if let Some(count) = param.downcast_ref::<AtomicU32>() {
count.fetch_add(1, Ordering::SeqCst);
}
Ok(param)
}).unwrap();
worker.delete();
counting.delete();
assert_eq!(WORK.load(Ordering::SeqCst), 3);
assert_eq!(counter.downcast_ref::<AtomicU32>().unwrap().load(Ordering::SeqCst), 1);Required Methods§
Sourcefn is_null(&self) -> bool
fn is_null(&self) -> bool
Returns true if the underlying OS handle is null, i.e. the thread
has not been spawned yet or has already been deleted.
Sourcefn spawn<F>(&mut self, param: Option<ThreadParam>, callback: F) -> Result<Self>where
F: Fn(Box<dyn Thread>, Option<ThreadParam>) -> Result<ThreadParam> + Send + Sync + 'static,
Self: Sized,
fn spawn<F>(&mut self, param: Option<ThreadParam>, callback: F) -> Result<Self>where
F: Fn(Box<dyn Thread>, Option<ThreadParam>) -> Result<ThreadParam> + Send + Sync + 'static,
Self: Sized,
Spawns a thread with a callback function and optional parameter.
Creates and starts a new thread that executes the provided callback function. The callback receives a handle to itself and an optional parameter.
§Parameters
param- Optional type-erased parameter passed to the callbackcallback- Function to execute in the thread context
§Returns
Ok(Self)- Thread spawned successfullyErr(Error)- Failed to create or start thread
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
static SEEN: AtomicU32 = AtomicU32::new(0);
let mut thread = Thread::new("worker", 1024, 5);
let counter: ThreadParam = Arc::new(100u32);
let spawned = thread.spawn(Some(counter.clone()), |_thread, param| {
if let Some(p) = param {
if let Some(count) = p.downcast_ref::<u32>() {
SEEN.store(*count, Ordering::SeqCst);
}
}
Ok(Arc::new(200u32))
}).unwrap();
spawned.delete(); // waits for the thread to finish
assert_eq!(SEEN.load(Ordering::SeqCst), 100);Sourcefn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
fn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
Spawns a simple thread with a callback function (no parameters).
Creates and starts a new thread that executes the provided callback.
This is a simpler version of spawn() for threads that don’t need
parameters or self-reference.
§Parameters
callback- Function to execute in the thread context
§Returns
Ok(Self)- Thread spawned successfullyErr(Error)- Failed to create or start thread
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
static LED: AtomicBool = AtomicBool::new(false);
let mut thread = Thread::new("blinker", 512, 3);
let blinker = thread.spawn_simple(|| {
for _ in 0..4 {
LED.fetch_xor(true, Ordering::SeqCst); // toggle the LED
System::delay(5);
}
Ok(Arc::new(()))
}).unwrap();
blinker.delete();
assert!(!LED.load(Ordering::SeqCst)); // toggled an even number of timesSourcefn delete(&self)
fn delete(&self)
Deletes the thread and frees its resources.
Terminates the thread and releases its stack and control structures. After calling this, the thread handle becomes invalid.
§Safety
- The thread should not be holding any resources (mutexes, etc.)
- Other threads should not be waiting on this thread
- Cannot delete the currently running thread (use from another thread)
§Examples
use osal_rs::os::*;
use std::sync::Arc;
let mut thread = Thread::new("temp", 512, 1);
let spawned = thread.spawn_simple(|| {
// Do some work
System::delay(5);
Ok(Arc::new(()))
}).unwrap();
// Later, from another thread
spawned.delete();Sourcefn suspend(&self)
fn suspend(&self)
Suspends the thread.
Prevents the thread from executing until resume() is called.
The thread state is preserved and can be resumed later.
§Use Cases
- Temporarily pause a thread
- Debugging and development
- Dynamic task management
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
static COUNTER: AtomicU32 = AtomicU32::new(0);
let mut thread = Thread::new("counter", 1024, 1);
let worker = thread.spawn_simple(|| {
loop {
COUNTER.fetch_add(1, Ordering::SeqCst);
System::delay(1);
}
}).unwrap();
System::delay(30);
worker.suspend(); // Pauses the worker, not the caller
let paused_at = COUNTER.load(Ordering::SeqCst);
System::delay(50);
// No progress while suspended.
assert_eq!(COUNTER.load(Ordering::SeqCst), paused_at);
worker.resume();Sourcefn resume(&self)
fn resume(&self)
Resumes a suspended thread.
Resumes execution of a thread that was previously suspended with suspend().
If the thread was not suspended, this has no effect.
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
static COUNTER: AtomicU32 = AtomicU32::new(0);
let mut thread = Thread::new("counter", 1024, 1);
let worker_thread = thread.spawn_simple(|| {
loop {
COUNTER.fetch_add(1, Ordering::SeqCst);
System::delay(1);
}
}).unwrap();
System::delay(30);
worker_thread.suspend();
let paused_at = COUNTER.load(Ordering::SeqCst);
System::delay(50);
worker_thread.resume(); // Resume the worker
System::delay(30);
// Progress resumes.
assert!(COUNTER.load(Ordering::SeqCst) > paused_at);Sourcefn join(&self, retval: DoublePtr) -> Result<i32>
fn join(&self, retval: DoublePtr) -> Result<i32>
Waits for the thread to complete and retrieves its return value.
Blocks the calling thread until this thread terminates. The thread’s return value is stored in the provided pointer.
§Parameters
retval- Pointer to store the thread’s return value
§Returns
Ok(exit_code)- Thread completed successfullyErr(Error)- Join operation failed
§Examples
use osal_rs::os::*;
use std::sync::Arc;
let mut thread = Thread::new("worker", 1024, 1);
let spawned = thread.spawn_simple(|| {
// Do work
Ok(Arc::new(()))
}).unwrap();
// Pass a null pointer when the exit value is not needed.
assert!(spawned.join(core::ptr::null_mut()).is_ok());Sourcefn get_metadata(&self) -> ThreadMetadata
fn get_metadata(&self) -> ThreadMetadata
Gets metadata about the thread.
Returns information such as thread name, priority, stack usage, and current state.
§Returns
ThreadMetadata structure containing thread information
§Examples
use osal_rs::os::*;
let thread = Thread::new("worker", 1024, 3);
let meta = thread.get_metadata();
assert_eq!(meta.name.as_str(), "worker");
assert_eq!(meta.priority, 3);Sourcefn get_current() -> Selfwhere
Self: Sized,
fn get_current() -> Selfwhere
Self: Sized,
Gets a handle to the currently executing thread.
Returns a handle to the thread that is currently running. Useful for self-referential operations.
§Returns
Handle to the current thread
§Examples
use osal_rs::os::*;
let current = Thread::get_current();
assert!(!current.is_null());
let meta = current.get_metadata();
assert_eq!(meta.state, ThreadState::Running);Sourcefn notify(&self, notification: ThreadNotification) -> Result<()>
fn notify(&self, notification: ThreadNotification) -> Result<()>
Sends a notification to the thread.
Notifies the thread using the specified notification action. Task notifications are a lightweight signaling mechanism.
§Parameters
notification- The notification action to perform
§Returns
Ok(())- Notification sent successfullyErr(Error)- Failed to send notification
§Examples
use osal_rs::os::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
static RECEIVED: AtomicU32 = AtomicU32::new(0);
let mut thread = Thread::new("worker", 1024, 1);
let worker = thread.spawn_simple(|| {
let current = Thread::get_current();
// Blocks until the notification below arrives.
let value = current.wait_notification(0, 0, 1000).unwrap();
RECEIVED.store(value, Ordering::SeqCst);
Ok(Arc::new(()))
}).unwrap();
// Send a value. `ThreadNotification::SetBits` would signal an event
// instead, without disturbing the bits another event already set.
worker.notify(ThreadNotification::SetValueWithOverwrite(42)).unwrap();
worker.delete();
assert_eq!(RECEIVED.load(Ordering::SeqCst), 42);Sourcefn notify_from_isr(
&self,
notification: ThreadNotification,
higher_priority_task_woken: &mut BaseType,
) -> Result<()>
fn notify_from_isr( &self, notification: ThreadNotification, higher_priority_task_woken: &mut BaseType, ) -> Result<()>
Sends a notification to the thread from ISR context.
ISR-safe version of notify(). Must only be called from interrupt context.
§Parameters
notification- The notification action to performhigher_priority_task_woken- Set to non-zero if a context switch should occur
§Returns
Ok(())- Notification sent successfullyErr(Error)- Failed to send notification
§Examples
use osal_rs::os::*;
// In interrupt handler
fn isr_handler(worker: &Thread) {
let mut task_woken = 0;
worker.notify_from_isr(
ThreadNotification::Increment,
&mut task_woken
).ok();
System::yield_from_isr(task_woken);
}
let current = Thread::get_current();
isr_handler(¤t);
// The notification is now pending on the notified thread.
assert_eq!(current.wait_notification(0, 0xFFFF_FFFF, 10).unwrap(), 1);Sourcefn wait_notification(
&self,
bits_to_clear_on_entry: u32,
bits_to_clear_on_exit: u32,
timeout_ticks: TickType,
) -> Result<u32>
fn wait_notification( &self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32, timeout_ticks: TickType, ) -> Result<u32>
Waits for a notification.
Blocks the calling thread until a notification is received or timeout occurs. Allows clearing specific bits on entry and/or exit.
§Parameters
bits_to_clear_on_entry- Bits to clear before waitingbits_to_clear_on_exit- Bits to clear after receiving notificationtimeout_ticks- Maximum ticks to wait (0 = no wait, MAX = wait forever)
§Returns
Ok(notification_value)- Notification received, returns the notification valueErr(Error::Timeout)- No notification received within timeoutErr(Error)- Other error occurred
§Note
This method does not use ToTick trait to maintain dynamic dispatch compatibility.
§Examples
use osal_rs::os::*;
let current = Thread::get_current();
// Nothing pending yet: this gives up once the timeout expires rather
// than blocking forever.
assert!(current.wait_notification(0, 0, 10).is_err());
// Wait for notification, clear all bits on exit
current.notify(ThreadNotification::SetValueWithOverwrite(7)).unwrap();
match current.wait_notification(0, 0xFFFFFFFF, 1000) {
Ok(value) => assert_eq!(value, 7),
Err(_) => panic!("timeout waiting for notification"),
}
// Wait for specific bits
let bits_of_interest = 0b0011;
current.notify(ThreadNotification::SetBits(bits_of_interest)).unwrap();
match current.wait_notification(0, bits_of_interest, 5000) {
Ok(value) => assert_ne!(value & bits_of_interest, 0),
Err(_) => panic!("timeout"),
}Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".