I'm a developer

            
pub fn push(&self, value: T) -> &T {
let mut item = ManuallyDrop::new(value);
loop {
let last = self.last.load(Ordering::Acquire);

// Both of these are from the same `RoseInner`
// SAFETY: Last is always a valid pointer.
let length = unsafe { &(*last).length };
let capacity = unsafe { (*last).capacity };
let index = length.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
if x == capacity {
// We need to allocate more.
None
} else {
Some(x + 1)
}
});

if let Ok(len) = index {
// SAFETY: last is a valid pointer.
// We use AcqRel to ensure that other threads are aware we're writing.
unsafe { (*last).writers.fetch_add(1, Ordering::AcqRel) };
// `writers` cannot overflow because its always less than or equal to`capacity`.
// SAFETY: We now "own" the index, as the index was increased, so we can write to it.
unsafe {
let out = addr_of_mut!((*last).data).cast::<T>().add(len);
out.write(addr_of!(item).cast::<T>().read());
let writers = (*last).writers.fetch_sub(1, Ordering::AcqRel) - 1;
let _ = (*last).active_index.fetch_update(
Ordering::AcqRel,
Ordering::Acquire,
|x| {
// If we are the next write or we are the last writer,
// we can set the active index.
if x == len || writers == 0 {
Some(len + 1)
} else {
None
}
},
);

// SAFETY: last is a valid pointer.
return &*out;
}
}

let new = Self::alloc(capacity * 2);
// SAFETY: We just created the pointer, so we can do whatever we want with it.
let refer = unsafe {
let new = new.as_ptr();
addr_of_mut!((*new).next).write(last);
addr_of_mut!((*new).length).write(AtomicUsize::new(1));
addr_of_mut!((*new).capacity).write(capacity * 2);
addr_of_mut!((*new).writers).write(AtomicUsize::new(0));
addr_of_mut!((*new).active_index).write(AtomicUsize::new(1));
let out = addr_of_mut!((*new).data).cast::<T>();
out.write(addr_of_mut!(item).cast::<T>().read());
&*out
};
let success = self
.last
.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
if x == last {
Some(new.as_ptr())
} else {
// Somebody changed our pointer.
None
}
});
if success.is_ok() {
return refer;
}
// Another thread updated the pointer before us.
// SAFETY: We just created the pointer via alloc, so we can deallocate it.
unsafe {
dealloc(new.as_ptr().cast::<u8>(), Self::layout(capacity * 2));
};
}
}

Click on the green to move the box

(This uses no JS)

Move to the next page

Integrals

Memory

Floats

Assorted Projects

Linear Algebra

Notes