summaryrefslogtreecommitdiff
path: root/ucoo
diff options
context:
space:
mode:
authorNicolas Schodet2015-10-21 00:43:21 +0200
committerNicolas Schodet2019-10-07 00:44:50 +0200
commita3ad7336b71c74f22a40ad8bb11fc96b99431672 (patch)
tree170b147b456af79f8797e38c9808db55963ccbc9 /ucoo
parentf66a9863c2b5d29ee2d3c57b65a0aecc9656c59c (diff)
ucoo/utils/fifo: add poll, read_peek, drop
Diffstat (limited to 'ucoo')
-rw-r--r--ucoo/utils/fifo.hh7
-rw-r--r--ucoo/utils/fifo.tcc39
-rw-r--r--ucoo/utils/test/test_fifo.cc4
3 files changed, 50 insertions, 0 deletions
diff --git a/ucoo/utils/fifo.hh b/ucoo/utils/fifo.hh
index 2e55eb5..3b4aada 100644
--- a/ucoo/utils/fifo.hh
+++ b/ucoo/utils/fifo.hh
@@ -52,9 +52,16 @@ class Fifo
/// Pop up to COUNT elements and store them in BUF. Return the number of
/// read elements.
int read (T *buf, int count);
+ /// Read up to COUNT elements and store them in BUF. Return the number of
+ /// read elements. Do not pop read elements.
+ int read_peek (T *buf, int count);
+ /// Drop COUNT elements, do not do that if COUNT elements are not present!
+ void drop (int count);
/// Push up to COUNT elements from BUF. Return the number of written
/// elements.
int write (const T *buf, int count);
+ /// Return the number of available elements to be read.
+ int poll ();
private:
/// Return next index, use unsigned operation for optimisation.
int next (int index) const
diff --git a/ucoo/utils/fifo.tcc b/ucoo/utils/fifo.tcc
index 9612605..f658f99 100644
--- a/ucoo/utils/fifo.tcc
+++ b/ucoo/utils/fifo.tcc
@@ -90,6 +90,38 @@ Fifo<T, size>::read (T *buf, int count)
}
template<typename T, int size>
+int
+Fifo<T, size>::read_peek (T *buf, int count)
+{
+ // Reader, can only update head.
+ int r = 0;
+ int head = head_;
+ int tail = access_once (tail_);
+ while (r < count && head != tail)
+ {
+ buf[r] = buffer_[head];
+ head = next (head);
+ r++;
+ }
+ // Do not update head.
+ return r;
+}
+
+template<typename T, int size>
+void
+Fifo<T, size>::drop (int count)
+{
+ // Reader, can only update head.
+ int head = head_;
+ for (int i = 0; i < count; i++)
+ {
+ assert (head != tail_);
+ head = next (head);
+ }
+ head_ = head;
+}
+
+template<typename T, int size>
inline int
Fifo<T, size>::write (const T *buf, int count)
{
@@ -111,6 +143,13 @@ Fifo<T, size>::write (const T *buf, int count)
return r;
}
+template<typename T, int size>
+int
+Fifo<T, size>::poll ()
+{
+ return (tail_ + size + 1 - head_) % (size + 1);
+}
+
} // namespace ucoo
#endif // ucoo_utils_fifo_tcc
diff --git a/ucoo/utils/test/test_fifo.cc b/ucoo/utils/test/test_fifo.cc
index 027fdd5..9f0f802 100644
--- a/ucoo/utils/test/test_fifo.cc
+++ b/ucoo/utils/test/test_fifo.cc
@@ -63,12 +63,16 @@ main (int argc, const char **argv)
{
r = fifo.write (b, 5);
test_fail_break_unless (test, r == 5);
+ test_fail_break_unless (test, fifo.poll () == 5);
r = fifo.read (c, 2);
test_fail_break_unless (test, r == 2 && c[0] == 1 && c[1] == 2);
+ test_fail_break_unless (test, fifo.poll () == 3);
r = fifo.write (b, 5);
test_fail_break_unless (test, r == 4);
+ test_fail_break_unless (test, fifo.poll () == 7);
r = fifo.read (c, 8);
test_fail_break_unless (test, r == 7);
+ test_fail_break_unless (test, fifo.poll () == 0);
test_fail_break_unless (test, c[0] == 3 && c[1] == 4 && c[2] == 5);
test_fail_break_unless (test, c[3] == 1 && c[4] == 2 && c[5] == 3
&& c[6] == 4);