
Atoman (atomic state, flag and more..)
Atoman is a Rust library for safe concurrent access to static asynchronous data across your application.
It provides atomic flags and state wrappers with async setters, getters, and locking mechanisms,
bridging synchronous static variables with async runtimes like Tokio.
It provides blocking methods alongside async APIs, enabling seamless use in both asynchronous (Tokio tasks)
and synchronous (threads/blocking code) contexts without deadlocks or runtime conflicts.
Features:
- Global configuration management with file-based persistence (
TOML/JSON).
- Structured logging with async-safe output to files.
- Real-time log file tracing using minimal memory stack.
- Feature flags and shared state in async applications.
- Data is stored in
Arc for zero-copy access and thread safety.
Examples:
Atomic Flag:
use atoman::prelude::*;
static IS_ACTIVE: Flag = Flag::new();
#[tokio::main]
async fn main() {
assert!(!IS_ACTIVE.get());
assert!(IS_ACTIVE.is_false());
IS_ACTIVE.set(true);
assert!(IS_ACTIVE.get());
IS_ACTIVE.swap(false).await;
assert!(!IS_ACTIVE.get());
IS_ACTIVE.blocking_swap(true);
assert!(IS_ACTIVE.get());
}
Atomic State:
use atoman::prelude::*;
static CONFIG: State<Config> = State::new();
#[derive(Default, Clone)]
pub struct Config {
pub count: i32,
}
#[tokio::main]
async fn main() {
CONFIG.set(Config { count: 10, }).await;
assert_eq!(CONFIG.get().await.count, 10);
CONFIG.blocking_set(Config { count: 15 });
assert_eq!(CONFIG.blocking_get().count, 15);
CONFIG.map(|cfg| cfg.count = 20).await;
assert_eq!(CONFIG.get().await.count, 20);
CONFIG.lock().await.count = 30;
assert_eq!(CONFIG.get().await.count, 30);
}
Config:
use atoman::prelude::*;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct Person {
name: String,
age: u32
}
impl Default for Person {
fn default() -> Self {
Self {
name: "Bob".to_owned(),
age: 23
}
}
}
#[tokio::main]
async fn main() -> Result<()> {
let mut cfg = Config::<Person>::new(".test/person.toml")?;
assert_eq!(cfg.name, "Bob");
assert_eq!(cfg.age, 23);
cfg.age = 24;
assert_eq!(cfg.age, 24);
Ok(())
}
Logger:
use atoman::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
Logger::init(".logs", 20)?;
info!("Hello, World!");
Ok(())
}
Tracing:
use atoman::{Logger, Trace, info, prelude::*};
use tokio::time::{Duration, sleep};
#[tokio::main]
async fn main() -> Result<()> {
Logger::init(".logs", 20)?;
info!("Logger initialized!");
let log_path = Logger::get_path().unwrap();
let trace_handle = tokio::spawn(async move {
let mut trace = Trace::open(log_path, Duration::from_millis(50), false)
.await
.expect("Failed to open trace");
let mut count = 0;
while count < 10 {
if let Some(line) = trace.next_line().await {
println!("Traced line: {}", line);
count += 1;
}
}
});
sleep(Duration::from_millis(100)).await;
for i in 1..=15 {
info!("Test log #{}", i);
sleep(Duration::from_millis(100)).await;
}
let _ = trace_handle.await;
Ok(())
}
Feedback:
This library distributed under the MIT license.
You can contact me via GitHub or send a message to my telegram @fuderis.
This library is actively evolving, and your suggestions and feedback are always welcome!