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