# nolocal-block-on Version of [`futures_lite::future::block_on`][fl-block-on] that does not use any thread locals internally. This is a very specialized crate designed for use in special parts of a program (such as in [`libc::atexit`][libc-atexit] callbacks, or things occurring pre- or post- main) where thread local storage will not function. If your future itself uses thread-local storage, though, then you're out of luck (or need to change the implementation of the futures you're using). You almost certainly want the normal [`futures_lite::future::block_on`][fl-block-on] except in specific circumstances as described above. ## Examples The way you invoke the function provided by this crate is the same as the [`futures-lite` version][fl-block-on]: ```rust let val = nolocal_block_on::block_on(async { 1 + 2 }); assert_eq!(val, 3); ``` However, the [`futures-lite` version][fl-block-on] does not work in (rare) places where thread-local storage cannot function - for example, running after the main rust runtime is getting shut down. To illustrate this, we demonstrate it via [`libc::atexit`][libc-atexit]. The following code, using [`futures_lite::future::block_on`][fl-block-on], might panic due to using thread-locals in the implementation - and in particular, when multiple threads are involved (such as with [`blocking::Unblock`][blocking-unblock]), it will panic consistently: ```rust,should_panic use futures_lite::{future::block_on, io::AsyncWriteExt}; use async_lock::Mutex; use std::{sync::LazyLock, io::{Stdout, self}}; use blocking::Unblock; static STDOUT: LazyLock>> = LazyLock::new(|| { Mutex::new(Unblock::new(io::stdout())) }); block_on(async { STDOUT.lock().await.write(b"hello program\n").await }); extern "C" fn cleanup() { block_on(async { let mut locked_stdout = STDOUT.lock().await; locked_stdout.write(b"goodbye program!\n").await; locked_stdout.flush().await; }); } unsafe { libc::atexit(cleanup); } ``` However, the following code using [`nolocal_block_on::block_on`][nl-block-on], will not panic, as the implementation doesn't use any thread-locals (for non-trivial futures, you might need to check to make sure they don't use thread-locals in their implementations): ```rust use nolocal_block_on::block_on; use futures_lite::io::AsyncWriteExt; use async_lock::Mutex; use std::{sync::LazyLock, io::{Stdout, self}}; use blocking::Unblock; static STDOUT: LazyLock>> = LazyLock::new(|| { Mutex::new(Unblock::new(io::stdout())) }); block_on(async { STDOUT.lock().await.write(b"hello program\n").await }); extern "C" fn cleanup() { block_on(async { let mut locked_stdout = STDOUT.lock().await; locked_stdout.write(b"goodbye program!\n").await; locked_stdout.flush().await; }); } unsafe { libc::atexit(cleanup); } ``` [fl-block-on]: https://docs.rs/futures-lite/latest/futures_lite/future/fn.block_on.html [nl-block-on]: https://docs.rs/nolocal-block-on/latest/nolocal_block_on/fn.block_on.html [libc-atexit]: https://docs.rs/libc/latest/libc/fn.atexit.html [blocking-unblock]: https://docs.rs/blocking/latest/blocking/struct.Unblock.html