hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use crate::gpu::Command;
use core::cell::UnsafeCell;
use core::sync::atomic::{AtomicUsize, Ordering};

const Q_SIZE: usize = 64;

pub struct Queue {
    ring: UnsafeCell<[Option<Command>; Q_SIZE]>,
    head: AtomicUsize,
    tail: AtomicUsize,
}

unsafe impl Sync for Queue {}

impl Default for Queue {
    fn default() -> Self {
        Self::new()
    }
}

impl Queue {
    pub fn new() -> Self {
        Queue {
            ring: UnsafeCell::new([None; Q_SIZE]),
            head: AtomicUsize::new(0),
            tail: AtomicUsize::new(0),
        }
    }

    pub fn enqueue(&self, cmd: Command) -> bool {
        let head = self.head.load(Ordering::Acquire);
        let tail = self.tail.load(Ordering::Acquire);
        let next = (head + 1) % Q_SIZE;
        if next == tail {
            return false;
        }
        unsafe {
            (*self.ring.get())[head] = Some(cmd);
        }
        self.head.store(next, Ordering::Release);
        true
    }

    pub fn dequeue(&self) -> Option<Command> {
        let tail = self.tail.load(Ordering::Acquire);
        let head = self.head.load(Ordering::Acquire);
        if tail == head {
            return None;
        }
        let cmd = unsafe { (*self.ring.get())[tail].take() };
        let next = (tail + 1) % Q_SIZE;
        self.tail.store(next, Ordering::Release);
        cmd
    }
}