blob: 21422130a612e01fcb32b8f263b4951ace33927c [file] [log] [blame]
Brian Silvermaneda63f32017-10-08 18:57:33 -04001#ifndef MOTORS_USB_QUEUE_H_
2#define MOTORS_USB_QUEUE_H_
3
Brian Silvermaneda63f32017-10-08 18:57:33 -04004#include <atomic>
Philipp Schrader790cb542023-07-05 21:06:52 -07005#include <memory>
Brian Silvermaneda63f32017-10-08 18:57:33 -04006
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08007namespace frc971::teensy {
Brian Silvermaneda63f32017-10-08 18:57:33 -04008
9// A FIFO queue which reads/writes variable-sized chunks.
10//
11// Reading data happens-after it is written. However, external synchronization
12// between multiple readers/writers is required.
13class Queue {
14 public:
15 Queue(size_t size) : size_(size), data_(new char[size]) {}
16
17 // Writes as much of in_data as will fit to the queue. Returns the number of
18 // bytes written.
19 size_t Write(const char *in_data, size_t in_size);
20
21 // Reads up to out_size from the queue into out_data. Returns the number of
22 // bytes read.
23 size_t Read(char *out_data, size_t out_size);
24
25 size_t data_queued() const {
26 return space_used(read_cursor_.load(::std::memory_order_relaxed),
27 write_cursor_.load(::std::memory_order_relaxed));
28 }
29
Philipp Schrader790cb542023-07-05 21:06:52 -070030 size_t space_available() const { return size_ - data_queued() - 1; }
Brian Silvermaneda63f32017-10-08 18:57:33 -040031
32 bool empty() const {
33 return read_cursor_.load(::std::memory_order_relaxed) ==
34 write_cursor_.load(::std::memory_order_relaxed);
35 }
36
37 private:
38 size_t space_used(size_t read_cursor, size_t write_cursor) const {
39 size_t r = write_cursor - read_cursor;
40 if (r > size_) {
41 r = size_ + r;
42 }
43 return r;
44 }
45
46 size_t wrap(size_t cursor) const {
47 if (cursor >= size_) {
48 return cursor - size_;
49 } else {
50 return cursor;
51 }
52 }
53
54 const size_t size_;
55 const ::std::unique_ptr<char[]> data_;
56
57 // The next index we're going to read from.
58 ::std::atomic<size_t> read_cursor_{0};
59 // The next index we're going to write to.
60 ::std::atomic<size_t> write_cursor_{0};
61};
62
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080063} // namespace frc971::teensy
Brian Silvermaneda63f32017-10-08 18:57:33 -040064
65#endif // MOTORS_USB_QUEUE_H_