1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! Implementation of a ring buffer.

use common::queue;
use core::ptr::read_volatile;

pub struct RingBuffer<'a, T: 'a> {
    ring: &'a mut [T],
    head: usize,
    tail: usize,
}

impl<'a, T: Copy> RingBuffer<'a, T> {
    pub fn new(ring: &'a mut [T]) -> RingBuffer<'a, T> {
        RingBuffer {
            head: 0,
            tail: 0,
            ring: ring,
        }
    }
}

impl<'a, T: Copy> queue::Queue<T> for RingBuffer<'a, T> {
    fn has_elements(&self) -> bool {
        unsafe {
            let head = read_volatile(&self.head);
            let tail = read_volatile(&self.tail);
            head != tail
        }
    }

    fn is_full(&self) -> bool {
        unsafe { read_volatile(&self.head) == ((read_volatile(&self.tail) + 1) % self.ring.len()) }
    }

    fn len(&self) -> usize {
        let head = unsafe { read_volatile(&self.head) };
        let tail = unsafe { read_volatile(&self.tail) };

        if tail > head {
            tail - head
        } else if tail < head {
            (self.ring.len() - head) + tail
        } else {
            // head equals tail, length is zero
            0
        }
    }

    fn enqueue(&mut self, val: T) -> bool {
        unsafe {
            let head = read_volatile(&self.head);
            if ((self.tail + 1) % self.ring.len()) == head {
                // Incrementing tail will overwrite head
                return false;
            } else {
                self.ring[self.tail] = val;
                self.tail = (self.tail + 1) % self.ring.len();
                return true;
            }
        }
    }

    fn dequeue(&mut self) -> Option<T> {
        if self.has_elements() {
            let val = self.ring[self.head];
            self.head = (self.head + 1) % self.ring.len();
            Some(val)
        } else {
            None
        }
    }
}