aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2018-02-02 21:20:19 +0100
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2018-02-02 21:20:19 +0100
commit57a2874206420e66d47ac079a8892aae19c7c127 (patch)
tree0e733af124304f7e654c71792f35bf55a3e09c16
parent5934814945eb4cec144db95bd076814869dbb4f2 (diff)
parenta95d6ab998b6b0fb8dc52bc3c0d682cb72bdff56 (diff)
downloadlibrb-57a2874206420e66d47ac079a8892aae19c7c127.tar.gz
librb-57a2874206420e66d47ac079a8892aae19c7c127.tar.bz2
librb-57a2874206420e66d47ac079a8892aae19c7c127.zip
add: rb_discard function to quickly discard data from buffer
-rw-r--r--include/rb.h1
-rw-r--r--man/Makefile.am1
-rw-r--r--man/rb_clear.31
-rw-r--r--man/rb_destroy.31
-rw-r--r--man/rb_discard.364
-rw-r--r--man/rb_new.31
-rw-r--r--man/rb_overview.71
-rw-r--r--man/rb_read.31
-rw-r--r--man/rb_space.31
-rw-r--r--man/rb_version.31
-rw-r--r--man/rb_write.31
-rw-r--r--rb/rb.c55
-rw-r--r--rb/tests.c65
-rw-r--r--readme.md2
14 files changed, 196 insertions, 0 deletions
diff --git a/include/rb.h b/include/rb.h
index 4e00305..aa17de8 100644
--- a/include/rb.h
+++ b/include/rb.h
@@ -36,6 +36,7 @@ long rb_send(struct rb *, const void *, size_t, unsigned long);
int rb_clear(struct rb *, int);
int rb_destroy(struct rb *);
int rb_stop(struct rb *);
+size_t rb_discard(struct rb *, size_t);
const char *rb_version(char *, char *, char *);
size_t rb_count(const struct rb *);
size_t rb_space(const struct rb *);
diff --git a/man/Makefile.am b/man/Makefile.am
index f827035..8816e97 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,6 +1,7 @@
man_MANS = rb_clear.3 \
rb_count.3 \
rb_destroy.3 \
+ rb_discard.3 \
rb_new.3 \
rb_overview.7 \
rb_read.3 \
diff --git a/man/rb_clear.3 b/man/rb_clear.3
index 66d03b4..0df73a2 100644
--- a/man/rb_clear.3
+++ b/man/rb_clear.3
@@ -35,6 +35,7 @@ is invalid (null).
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_destroy.3 b/man/rb_destroy.3
index 58107b0..8876a1d 100644
--- a/man/rb_destroy.3
+++ b/man/rb_destroy.3
@@ -121,6 +121,7 @@ is invalid (null).
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_read (3),
+.BR rb_discard (3),
.BR rb_recv (3),
.BR rb_write (3),
.BR rb_send (3),
diff --git a/man/rb_discard.3 b/man/rb_discard.3
new file mode 100644
index 0000000..040b6f7
--- /dev/null
+++ b/man/rb_discard.3
@@ -0,0 +1,64 @@
+.TH "rb_discard" "3" "25 January 2018 (v2.1.2)" "bofc.pl"
+.SH
+.PP
+.B rb_discard
+- allows to quickly discard part of buffer
+.SH SYNOPSIS
+.PP
+.BI "int rb_discard(struct rb *" rb ", size_t " count ");"
+.SH DESCRIPTION
+.PP
+Function
+.BR rb_discard(3)
+will remove
+.I count
+elements from
+.I rb
+buffer.
+This functions is very similar to calling
+.BR rb_read (3)
+and then discarding buffer, but this function is much better because when
+discarding with
+.BR rb_discard (3)
+there is no copying involved, so it's much faster.
+You can pass more
+.I count
+then there is in the buffer.
+Function never blocks calling thread.
+.PP
+Note, it is very difficult to discard data in multi-threaded environment with
+more than one reader per se.
+Thus it is inadvisible to use this function when there are two or more readers
+using same
+.I rb
+object.
+.SH RETURN VALUES
+.PP
+Function will return number of elements actually discarded fomr buffer. It is
+ok for function to return less elements than it was passed in
+.I count
+variable.
+This means there was less elements in
+.I rb
+than requested to be discarded.
+On errors -1 is returned.
+.SH ERRORS
+.PP
+.TP
+.B EINVAL
+.I rb
+is not a valid object.
+.SH SEE ALSO
+.PP
+.BR rb_overview (7),
+.BR rb_new (3),
+.BR rb_destroy (3),
+.BR rb_stop (3),
+.BR rb_read (3),
+.BR rb_recv (3),
+.BR rb_write (3),
+.BR rb_send (3),
+.BR rb_clear (3),
+.BR rb_count (3),
+.BR rb_space (3),
+.BR rb_version (3)
diff --git a/man/rb_new.3 b/man/rb_new.3
index 2dc945d..c34df0f 100644
--- a/man/rb_new.3
+++ b/man/rb_new.3
@@ -99,6 +99,7 @@ and
.PP
.BR rb_overview (7),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_overview.7 b/man/rb_overview.7
index 2469616..f6581cd 100644
--- a/man/rb_overview.7
+++ b/man/rb_overview.7
@@ -122,6 +122,7 @@ Please note, that example is missing error handling for simplicity.
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_read.3 b/man/rb_read.3
index 3505599..0b701bd 100644
--- a/man/rb_read.3
+++ b/man/rb_read.3
@@ -165,6 +165,7 @@ Returned only if threads are enabled.
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_space.3 b/man/rb_space.3
index 71dab9f..7f8f113 100644
--- a/man/rb_space.3
+++ b/man/rb_space.3
@@ -26,6 +26,7 @@ you can put on the buffer.
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_version.3 b/man/rb_version.3
index ea4452a..d8f7e0d 100644
--- a/man/rb_version.3
+++ b/man/rb_version.3
@@ -37,6 +37,7 @@ Function returns pointer to statically allocated string with full version, like
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/man/rb_write.3 b/man/rb_write.3
index 05957da..cef1e19 100644
--- a/man/rb_write.3
+++ b/man/rb_write.3
@@ -109,6 +109,7 @@ Returned only if threads are enabled.
.BR rb_overview (7),
.BR rb_new (3),
.BR rb_destroy (3),
+.BR rb_discard (3),
.BR rb_stop (3),
.BR rb_read (3),
.BR rb_recv (3),
diff --git a/rb/rb.c b/rb/rb.c
index 9e32a92..e3efd24 100644
--- a/rb/rb.c
+++ b/rb/rb.c
@@ -988,6 +988,61 @@ int rb_stop
/* ==========================================================================
+ Function that discards data from tail of buffer. This works just like
+ rb_reads function, but is way faster as there is no copying involved
+ ========================================================================== */
+
+
+size_t rb_discard
+(
+ struct rb *rb, /* rb object */
+ size_t count /* number of elements to discard */
+)
+{
+ size_t rbcount; /* number of elements in rb */
+ size_t cnte; /* number of elements in rb until overlap */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ VALID(EINVAL, rb);
+ VALID(EINVAL, rb->buffer);
+
+#if ENABLE_THREADS
+ if ((rb->flags & O_NONBLOCK) == 0)
+ {
+ pthread_mutex_lock(&rb->lock);
+ }
+#endif
+
+ cnte = rb_count_end(rb);
+ rbcount = rb_count(rb);
+
+ if (count > rbcount)
+ {
+ count = rbcount;
+ }
+
+ if (count > cnte)
+ {
+ rb->tail = count - cnte;
+ }
+ else
+ {
+ rb->tail += count;
+ rb->tail &= rb->count -1;
+ }
+
+#if ENABLE_THREADS
+ if ((rb->flags & O_NONBLOCK) == 0)
+ {
+ pthread_mutex_unlock(&rb->lock);
+ }
+#endif
+
+}
+
+
+/* ==========================================================================
Returns version of the library
========================================================================== */
diff --git a/rb/tests.c b/rb/tests.c
index a93cabe..2241f53 100644
--- a/rb/tests.c
+++ b/rb/tests.c
@@ -460,6 +460,70 @@ static void single_thread(void)
rb_destroy(rb);
}
+static void discard(void)
+{
+ char s[8] = "0123456";
+ char d[8];
+ int i;
+ struct rb *rb;
+
+ for (i = 0; i != 1; i++)
+ {
+ int flags;
+
+#if ENABLE_THREADS
+ flags = i ? O_MULTITHREAD : 0;
+#else
+ /*
+ * yup, if ENABLE_THREADS is 0, same code will be executed twice...
+ * it's not a bug, it's a feature! MORE TESTS NEVER HURT!
+ */
+
+ flags = 0;
+#endif
+ rb = rb_new(8, 1, 0);
+ rb_write(rb, s, 6);
+ rb_discard(rb, 3);
+ rb_read(rb, d, 3);
+ mt_fok(memcmp(d, "345", 3));
+ rb_clear(rb, 0);
+
+ rb_write(rb, s, 6);
+ rb_read(rb, d, 2);
+ rb_discard(rb, 2);
+ rb_read(rb, d, 2);
+ mt_fok(memcmp(d, "45", 2));
+ rb_clear(rb, 0);
+
+ /* overlap cases */
+ rb_write(rb, s, 7);
+ rb_read(rb, d, 5);
+ rb_write(rb, s, 5);
+ rb_discard(rb, 3);
+ rb_read(rb, d, 3);
+ mt_fok(memcmp(d, "123", 3));
+ rb_clear(rb, 0);
+
+ rb_write(rb, s, 7);
+ rb_read(rb, d, 5);
+ rb_write(rb, s, 5);
+ rb_discard(rb, 2);
+ rb_read(rb, d, 3);
+ mt_fok(memcmp(d, "012", 3));
+ rb_clear(rb, 0);
+
+ rb_write(rb, s, 7);
+ rb_read(rb, d, 5);
+ rb_write(rb, s, 5);
+ rb_discard(rb, 4);
+ rb_read(rb, d, 3);
+ mt_fok(memcmp(d, "234", 3));
+ rb_clear(rb, 0);
+
+ rb_destroy(rb);
+ }
+}
+
static void bad_count_value(void)
{
struct rb *rb;
@@ -520,6 +584,7 @@ int main(void)
mt_run(multithread_flag);
mt_run(nonblocking_flag);
mt_run(singlethread_eagain);
+ mt_run(discard);
#if ENABLE_THREADS
mt_run(multithread_eagain);
diff --git a/readme.md b/readme.md
index 048e89a..ab8b3fd 100644
--- a/readme.md
+++ b/readme.md
@@ -33,6 +33,8 @@ Additional functions are:
returns number of free space for number of elements
* [rb_stop](http://librb.kurwinet.pl/manuals/rb_stop.3.html) -
forces all threads to exit **rb_write** and **rb_read** functions
+ * [rb_discard](http://librb.kurwinet.pl/manuals/rb_discard.3.html) -
+ allows to quickly discard part of buffers data
Dependencies
============