Rust原子枚举操作库portable_atomic_enum的使用,实现跨平台线程安全的枚举原子操作
Rust原子枚举操作库portable_atomic_enum的使用,实现跨平台线程安全的枚举原子操作
portable_atomic_enum是一个从atomic_enum分叉出来的库,它可选地使用portable-atomic来支持更多目标平台。该库提供了一个属性宏来创建C风格枚举的原子包装器。
示例
# use atomic_enum::atomic_enum;
# use std::sync::atomic::Ordering;
#[atomic_enum]
#[derive(Clone, Copy, Debug, PartialEq)]
enum CatState {
Dead = 0,
BothDeadAndAlive,
Alive,
}
let state = AtomicCatState::new(CatState::Dead);
state.store(CatState::Alive, Ordering::Relaxed);
assert_eq!(state.load(Ordering::Relaxed), CatState::Alive);
该属性宏不会使用或生成任何不安全代码,并且可以在#[no_std]
环境中使用。
完整示例代码
下面是一个更完整的示例,展示如何在多线程环境中使用portable_atomic_enum:
use portable_atomic_enum::atomic_enum;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::thread;
// 定义一个状态枚举
#[atomic_enum]
#[derive(Clone, Copy, Debug, PartialEq)]
enum ThreadState {
Idle = 0,
Running,
Finished,
}
fn main() {
// 创建原子状态变量
let state = Arc::new(AtomicThreadState::new(ThreadState::Idle));
// 克隆Arc用于线程
let state_clone = Arc::clone(&state);
let handle = thread::spawn(move || {
// 线程开始时设置状态为Running
state_clone.store(ThreadState::Running, Ordering::SeqCst);
// 模拟工作
thread::sleep(std::time::Duration::from_secs(1));
// 工作完成后设置状态为Finished
state_clone.store(ThreadState::Finished, Ordering::SeqCst);
});
// 主线程监控状态变化
loop {
let current_state = state.load(Ordering::SeqCst);
println!("当前状态: {:?}", current_state);
if current_state == ThreadState::Finished {
break;
}
thread::sleep(std::time::Duration::from_millis(200));
}
handle.join().unwrap();
println!("线程完成!");
}
Cargo特性
portable-atomic
: 使用portable-atomic
作为原子类型的polyfill
特点
- 内部使用
AtomicUsize
存储枚举值 - 原子操作与
AtomicUsize
的等效操作具有相同的语义 - 不需要任何不安全代码
- 支持
#[no_std]
环境 - 跨平台支持
要使用这个库,只需在Cargo.toml中添加依赖:
portable_atomic_enum = "0.3.1"
1 回复
Rust原子枚举操作库portable_atomic_enum
使用指南
portable_atomic_enum
是一个Rust库,它提供了跨平台的线程安全枚举原子操作。这个库在需要以原子方式操作枚举值时特别有用,尤其是在多线程环境中。
特性
- 提供枚举类型的原子操作
- 跨平台支持
- 线程安全
- 类似标准库
std::sync::atomic
的API风格
安装
在Cargo.toml
中添加依赖:
[dependencies]
portable_atomic_enum = "0.1"
基本用法
定义可原子操作的枚举
首先,你需要定义一个枚举并使用#[derive(Atomic)]
宏:
use portable_atomic_enum::Atomic;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Atomic)]
enum State {
Idle,
Running,
Paused,
Stopped,
}
创建原子枚举变量
use portable_atomic_enum::AtomicEnum;
let atomic_state = AtomicEnum::new(State::Idle);
基本操作
// 存储值
atomic_state.store(State::Running, std::sync::atomic::Ordering::SeqCst);
// 加载值
let current_state = atomic_state.load(std::sync::atomic::Ordering::SeqCst);
println!("Current state: {:?}", current_state);
// 交换值
let previous_state = atomic_state.swap(State::Paused, std::sync::atomic::Ordering::SeqCst);
println!("Previous state: {:?}", previous_state);
比较并交换(CAS)
let mut expected = State::Paused;
loop {
match atomic_state.compare_exchange(
expected,
State::Running,
std::sync::atomic::Ordering::SeqCst,
std::sync::atomic::Ordering::Relaxed,
) {
Ok(_) => break,
Err(actual) => expected = actual,
}
}
高级用法
使用fetch_update
atomic_state.fetch_update(
std::sync::atomic::Ordering::SeqCst,
std::sync::atomic::Ordering::Relaxed,
|state| match state {
State::Idle => Some(State::Running),
State::Running => Some(State::Paused),
_ => None,
},
);
多线程示例
use std::sync::Arc;
use std::thread;
let shared_state = Arc::new(AtomicEnum::new(State::Idle));
let threads: Vec<_> = (0..4)
.map(|i| {
let state = shared_state.clone();
thread::spawn(move || {
// 每个线程尝试将状态改为Running
state.compare_exchange(
State::Idle,
State::Running,
std::sync::atomic::Ordering::SeqCst,
std::sync::atomic::Ordering::Relaxed,
).ok();
println!("Thread {} set state to Running", i);
})
})
.collect();
for t in threads {
t.join().unwrap();
}
println!("Final state: {:?}", shared_state.load(std::sync::atomic::Ordering::SeqCst));
内存顺序
和标准库的原子类型一样,portable_atomic_enum
支持多种内存顺序:
Relaxed
Acquire
Release
AcqRel
SeqCst
注意事项
- 枚举的大小不能超过指针大小(通常64位系统上是8字节)
- 枚举的表示必须是
#[repr(C)]
或#[repr(integer_type)]
,Atomic
派生宏会自动处理 - 对于复杂枚举,可能需要手动实现
Atomic
trait
portable_atomic_enum
为Rust中的枚举提供了简单而强大的原子操作能力,特别适合状态机实现和多线程环境下的状态管理。
完整示例代码
use portable_atomic_enum::{Atomic, AtomicEnum};
use std::sync::{Arc, atomic::Ordering};
use std::thread;
// 定义原子枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq, Atomic)]
enum TaskState {
Pending,
Processing,
Completed,
Failed,
}
fn main() {
// 创建原子枚举实例
let atomic_task = AtomicEnum::new(TaskState::Pending);
// 基本操作示例
println!("初始状态: {:?}", atomic_task.load(Ordering::SeqCst));
atomic_task.store(TaskState::Processing, Ordering::SeqCst);
println!("存储后状态: {:?}", atomic_task.load(Ordering::SeqCst));
let prev = atomic_task.swap(TaskState::Completed, Ordering::SeqCst);
println!("交换后前一个状态: {:?}", prev);
// CAS操作示例
let result = atomic_task.compare_exchange(
TaskState::Completed,
TaskState::Pending,
Ordering::SeqCst,
Ordering::Relaxed,
);
println!("CAS操作结果: {:?}", result);
// 多线程示例
let shared_task = Arc::new(AtomicEnum::new(TaskState::Pending));
let handles: Vec<_> = (0..3).map(|i| {
let task = shared_task.clone();
thread::spawn(move || {
// 使用fetch_update原子更新状态
task.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |state| {
match state {
TaskState::Pending => Some(TaskState::Processing),
TaskState::Processing => Some(TaskState::Completed),
_ => None,
}
}).unwrap();
println!("线程{}更新了任务状态", i);
})
}).collect();
for handle in handles {
handle.join().unwrap();
}
println!("最终任务状态: {:?}", shared_task.load(Ordering::SeqCst));
}
这个完整示例展示了portable_atomic_enum
库的主要功能:
- 定义原子枚举类型
- 基本原子操作(load/store/swap)
- 比较并交换(CAS)操作
- 多线程环境下的安全状态更新
- 使用fetch_update进行复杂状态转换
输出结果会显示任务状态在不同线程间的原子转换过程。