Skip to main content

celox_runtime/
event_buffer.rs

1use std::cell::UnsafeCell;
2use std::sync::atomic::{AtomicU64, Ordering};
3
4pub struct RuntimeEventBuffer {
5    words: Box<[UnsafeCell<u64>]>,
6    byte_size: usize,
7}
8
9unsafe impl Send for RuntimeEventBuffer {}
10unsafe impl Sync for RuntimeEventBuffer {}
11
12impl RuntimeEventBuffer {
13    pub fn new(byte_size: usize) -> Self {
14        let word_count = byte_size.div_ceil(8);
15        let words = (0..word_count)
16            .map(|_| UnsafeCell::new(0u64))
17            .collect::<Vec<_>>()
18            .into_boxed_slice();
19        Self { words, byte_size }
20    }
21
22    pub fn as_ptr(&self) -> *const u8 {
23        self.words.as_ptr() as *const u8
24    }
25
26    pub fn as_mut_ptr(&self) -> *mut u8 {
27        self.words.as_ptr() as *mut u8
28    }
29
30    pub fn byte_size(&self) -> usize {
31        self.byte_size
32    }
33
34    pub fn load_atomic_u64(&self, byte_offset: usize, ordering: Ordering) -> u64 {
35        assert_eq!(byte_offset % 8, 0);
36        assert!(byte_offset + 8 <= self.byte_size);
37        let word = byte_offset / 8;
38        unsafe {
39            let ptr = self.words[word].get() as *const AtomicU64;
40            (*ptr).load(ordering)
41        }
42    }
43
44    pub fn read_u64(&self, byte_offset: usize) -> u64 {
45        assert_eq!(byte_offset % 8, 0);
46        assert!(byte_offset + 8 <= self.byte_size);
47        let word = byte_offset / 8;
48        unsafe { std::ptr::read_volatile(self.words[word].get()) }
49    }
50
51    pub fn reset(&self) {
52        for word in &self.words {
53            unsafe {
54                std::ptr::write_volatile(word.get(), 0);
55            }
56        }
57    }
58}