Skip to main content

LocalKey

Struct LocalKey 

Source
pub struct LocalKey<T: 'static>(/* private fields */);
Expand description

A task-local storage key for mutable values.

This type allows you to store data that is unique to each async task, similar to thread-local storage but scoped to async tasks instead of threads.

§Examples

some_executor::task_local! {
    static MY_VALUE: u32;
}

async fn example() {
    // Set a value for the current task
    MY_VALUE.set(42);
     
    // Get the value
    assert_eq!(MY_VALUE.get(), 42);
     
    // Replace the value
    let old = MY_VALUE.replace(100);
    assert_eq!(old, 42);
    assert_eq!(MY_VALUE.get(), 100);
}

Task-local values are not inherited by spawned tasks.

Implementations§

Source§

impl<T: 'static> LocalKey<T>

Source

pub fn scope<F>( &'static self, value: T, f: F, ) -> impl Future<Output = F::Output>
where F: Future, T: Unpin,

Sets the task-local value for the duration of a future.

The value will be available to the future and any code it calls, but will be removed when the future completes.

§Examples
task_local! {
    static ID: u64;
}

async fn process() {
    println!("Processing with ID: {}", ID.get());
}

async fn main_task() {
    ID.scope(123, async {
        process().await; // Will print "Processing with ID: 123"
         
        ID.scope(456, async {
            process().await; // Will print "Processing with ID: 456"
        }).await;
         
        process().await; // Will print "Processing with ID: 123"
    }).await;
     
    // ID.get() would panic here because it's outside the scope
}
Source

pub fn with<F, R>(&'static self, f: F) -> R
where F: FnOnce(Option<&T>) -> R,

Accesses the task-local value through a closure.

This is the safest way to access a task-local value as it handles the case where the value might not be set.

§Examples
task_local! {
    static CONFIG: String;
}

async fn get_config_len() -> usize {
    CONFIG.with(|config| {
        config.map(|s| s.len()).unwrap_or(0)
    })
}

async fn example() {
    // Before setting, the value is None
    let len = get_config_len().await;
    assert_eq!(len, 0);
     
    CONFIG.scope("production".to_string(), async {
        let len = get_config_len().await;
        assert_eq!(len, 10);
    }).await;
}
Source

pub fn with_mut<F, R>(&'static self, f: F) -> R
where F: FnOnce(Option<&mut T>) -> R,

Accesses the task-local value mutably through a closure.

This allows you to modify the task-local value in place.

§Examples
task_local! {
    static COUNTER: Vec<i32>;
}

async fn increment_counter() {
    COUNTER.with_mut(|counter| {
        if let Some(vec) = counter {
            vec.push(vec.len() as i32);
        }
    });
}

async fn example() {
    COUNTER.scope(vec![0], async {
        increment_counter().await;
        increment_counter().await;
         
        COUNTER.with(|counter| {
            assert_eq!(counter.unwrap(), &vec![0, 1, 2]);
        });
    }).await;
}
Source

pub fn get(&'static self) -> T
where T: Copy,

Returns a copy of the task-local value.

§Panics

Panics if the task-local value is not set.

§Examples
task_local! {
    static ID: u64;
}

async fn get_current_id() -> u64 {
    ID.get()
}

async fn example() {
    ID.scope(42, async {
        let id = get_current_id().await;
        assert_eq!(id, 42);
    }).await;
}

Use with for safe access without panicking:

async fn get_id_or_default() -> u64 {
    ID.with(|id| id.copied().unwrap_or(0))
}
Source

pub fn set(&'static self, value: T)

Sets the task-local value.

This directly sets the value without running any lazy initialization. If a value was already set, it will be replaced.

§Examples
task_local! {
    static NAME: String;
}

async fn example() {
    // Set initial value
    NAME.set("Alice".to_string());
    NAME.with(|name| {
        assert_eq!(name.unwrap(), "Alice");
    });
     
    // Replace with new value
    NAME.set("Bob".to_string());
    NAME.with(|name| {
        assert_eq!(name.unwrap(), "Bob");
    });
}
Source

pub fn replace(&'static self, value: T) -> T

Replaces the task-local value, returning the old value.

§Panics

Panics if the task-local value is not set.

§Examples
task_local! {
    static GENERATION: u32;
}

async fn next_generation() -> u32 {
    let current = GENERATION.get();
    GENERATION.replace(current + 1)
}

async fn example() {
    GENERATION.set(1);
     
    let old = next_generation().await;
    assert_eq!(old, 1);
    assert_eq!(GENERATION.get(), 2);
     
    let old = next_generation().await;
    assert_eq!(old, 2);
    assert_eq!(GENERATION.get(), 3);
}

Trait Implementations§

Source§

impl<T: Debug + 'static> Debug for LocalKey<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> Freeze for LocalKey<T>

§

impl<T> RefUnwindSafe for LocalKey<T>

§

impl<T> Send for LocalKey<T>

§

impl<T> Sync for LocalKey<T>

§

impl<T> Unpin for LocalKey<T>

§

impl<T> UnwindSafe for LocalKey<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.