diff options
author | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2018-02-02 21:20:19 +0100 |
---|---|---|
committer | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2018-02-02 21:20:19 +0100 |
commit | 57a2874206420e66d47ac079a8892aae19c7c127 (patch) | |
tree | 0e733af124304f7e654c71792f35bf55a3e09c16 | |
parent | 5934814945eb4cec144db95bd076814869dbb4f2 (diff) | |
parent | a95d6ab998b6b0fb8dc52bc3c0d682cb72bdff56 (diff) | |
download | librb-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.h | 1 | ||||
-rw-r--r-- | man/Makefile.am | 1 | ||||
-rw-r--r-- | man/rb_clear.3 | 1 | ||||
-rw-r--r-- | man/rb_destroy.3 | 1 | ||||
-rw-r--r-- | man/rb_discard.3 | 64 | ||||
-rw-r--r-- | man/rb_new.3 | 1 | ||||
-rw-r--r-- | man/rb_overview.7 | 1 | ||||
-rw-r--r-- | man/rb_read.3 | 1 | ||||
-rw-r--r-- | man/rb_space.3 | 1 | ||||
-rw-r--r-- | man/rb_version.3 | 1 | ||||
-rw-r--r-- | man/rb_write.3 | 1 | ||||
-rw-r--r-- | rb/rb.c | 55 | ||||
-rw-r--r-- | rb/tests.c | 65 | ||||
-rw-r--r-- | readme.md | 2 |
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), @@ -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 ========================================================================== */ @@ -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); @@ -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 ============ |