Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

Does my lockfree stack impl look correct?

Дата публикации: 05-10-2026 17:23:37


use std::mem::MaybeUninit;
use sync::*; // pub(crate) use std::sync::atomic::{AtomicPtr, Ordering, fence};
mod sync;
struct Stack<T> {
head: AtomicPtr<Node<T>>,
}
impl<T> Drop for Stack<T> {
fn drop(&mut self) {
// todo!()
}
}
unsafe impl<T: Send> Send for Stack<T> {}
unsafe impl<T> Sync for Stack<T> {}
struct Node<T> {
data: MaybeUninit<T>,
next: *mut Node<T>,
}
impl<T> Stack<T> {
fn new() -> Self {
Self {
head: AtomicPtr::new(std::ptr::null_mut()),
}
}
fn push(&self, data: T) {
let node = Box::into_raw(Box::new(Node {
data: MaybeUninit::new(data),
next: std::ptr::null_mut(),
}));
let mut head = self.head.load(Ordering::Relaxed);
loop {
unsafe { &mut *node }.next = head;
match self
.head
.compare_exchange_weak(head, node, Ordering::Release, Ordering::Relaxed)
{
Ok(_) => break,
Err(actual) => {
head = actual;
}
}
}
}
fn pop(&self) -> Option<T> {
let mut head = self.head.load(Ordering::Relaxed);
// this fence prevents the above load from loading a detached head...
// because a detached head is deallocated and we might dereference it to reach `next`.
fence(Ordering::SeqCst); // a SC fence here (to synchronize with the below fence)
loop {
if head.is_null() {
return None;
}
let next = unsafe { &*head }.next;
match self
.head
.compare_exchange_weak(head, next, Ordering::Relaxed, Ordering::Relaxed)
{
Ok(head) => {
fence(Ordering::SeqCst); // a SC fence here
let data = unsafe { (&mut *head).data.assume_init_read() };
drop(unsafe { Box::from_raw(head) });
return Some(data);
}
Err(actual) => {
head = actual;
}
}
}
}
}
some things that could be wrong and are confusing:
mixing memory orderings with SeqCst, should I avoid this? Is the behavior unpredictable?
Does SeqCst Ordering act correctly on the load? (an Acquire fence is placed below the load, so I just placed the SeqCst fence below as well.)
Can the job be done with just a single SeqCst fence?
How to test this? I tried testing this very basic implementation using loom, but loom doesn't seem to be complaining even when I comment out the fences
I know that I could have used some very nice crates for memory reclamation here, but I was just trying things. Same thing goes for using fences and not using Ordering::SeqCst directly on the atomic operation
13 posts - 4 participants
Read full topic

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Type erasure and dyn lifetime in a NonNull/Box struct field08.5504-10-2026
2Are there wait-free priority queue crates?016.0905-10-2026
3Arena's and alignment07.304-10-2026
4Architecture review of a Hyper/Tower-based web framework (Toxi)015.4606-10-2026
5Strategies for dyn trait objects with optional behavior?07.1206-10-2026
6Why no Dependent Matrix Type?05.1608-10-2026
7What's everyone working on this week (41/2026)?020.3406-10-2026
8Calling static C++ method from Rust09.9404-10-2026
9Optimization of inlined functions returning Result?07.3606-10-2026
10Why is f32/f64::sqrt not const?022.7206-10-2026

Классификация: . Схожих патентов: 0. Схожих новостей: 10. Тональность: 0. Информативность: 6.06. Источник: users.rust-lang.org.