aboutsummaryrefslogtreecommitdiffstats
path: root/rb
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2018-01-14 20:10:17 +0100
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2018-01-14 20:56:04 +0100
commitcebe52e4ccac463a25f989af01d75b6b7cf65727 (patch)
treeb04844e599f5ca633e2e4bd0ccb17186fb65c693 /rb
parentf65d8a06e55882a93f226c96f237921f28169547 (diff)
downloadlibrb-cebe52e4ccac463a25f989af01d75b6b7cf65727.tar.gz
librb-cebe52e4ccac463a25f989af01d75b6b7cf65727.tar.bz2
librb-cebe52e4ccac463a25f989af01d75b6b7cf65727.zip
added: allow peeking into multi-threaded rb object
Diffstat (limited to 'rb')
-rw-r--r--rb/mtest.h53
-rw-r--r--rb/rb.c17
-rw-r--r--rb/tests.c48
3 files changed, 108 insertions, 10 deletions
diff --git a/rb/mtest.h b/rb/mtest.h
index 654d3c6..8f177d2 100644
--- a/rb/mtest.h
+++ b/rb/mtest.h
@@ -4,7 +4,7 @@
========================================================================== */
-/* ==== mtest version v0.1.0 ================================================ */
+/* ==== mtest version v0.2.0 ================================================ */
/* ==========================================================================
@@ -35,6 +35,20 @@
/* ==========================================================================
+ macro with extern declarations of variables defined by mt_defs(). This
+ macro should be called in any .c file, that uses mt_* function and does
+ not have mt_defs() called in.
+ ========================================================================== */
+
+
+#define mt_defs_ext() \
+ extern const char *curr_test; \
+ extern int mt_test_status; \
+ extern int mt_total_tests; \
+ extern int mt_total_failed;
+
+
+/* ==========================================================================
macro runs test 'f'. 'f' is just a function (without parenthesis ()).
========================================================================== */
@@ -63,14 +77,15 @@
#define mt_assert(e) do { \
if (!(e)) \
{ \
- fprintf(stdout, "# assert %d: %s, %s\n", __LINE__, curr_test, #e); \
+ fprintf(stdout, "# assert [%s:%d] %s, %s\n", \
+ __FILE__, __LINE__, curr_test, #e); \
mt_test_status = -1; \
return; \
} } while (0)
/* ==========================================================================
- same as mt_assert, but function is not forced to return, and test can
+ same as mt_assert, but function is not forced to return, and test can
continue
========================================================================== */
@@ -78,15 +93,37 @@
#define mt_fail(e) do { \
if (!(e)) \
{ \
- fprintf(stdout, "# assert %d: %s, %s\n", __LINE__, curr_test, #e); \
+ fprintf(stdout, "# assert [%s:%d] %s, %s\n", \
+ __FILE__, __LINE__, curr_test, #e); \
mt_test_status = -1; \
- } } while(0)
+ } } while (0)
+
+
+/* ==========================================================================
+ shortcut macro to test if function exits with success (with return value
+ set to 0)
+ ========================================================================== */
+
+
+#define mt_fok(e) mt_fail(e == 0)
+
+
+/* ==========================================================================
+ shortcut macro to test if function fails as expected, with return code
+ set to -1, and expected errno errn
+ ========================================================================== */
+
+#define mt_ferr(e, errn) do { \
+ errno = 0; \
+ mt_fail(e == -1); \
+ mt_fail(errno == errn); \
+ } while (0)
/* ==========================================================================
- prints test plan, in format 1..<number_of_test_run>. If all tests have
- passed, macro will return current function with code 0, else it returns
- number of failed tests. If number of failed tests exceeds 254, then 254
+ prints test plan, in format 1..<number_of_test_run>. If all tests have
+ passed, macro will return current function with code 0, else it returns
+ number of failed tests. If number of failed tests exceeds 254, then 254
will be returned
========================================================================== */
diff --git a/rb/rb.c b/rb/rb.c
index ba31997..398c44b 100644
--- a/rb/rb.c
+++ b/rb/rb.c
@@ -801,7 +801,22 @@ long rb_recv
rb->tinread++;
pthread_mutex_unlock(&rb->lock);
- count = rb_recvt(rb, buffer, count, flags);
+ if (flags & MSG_PEEK)
+ {
+ /*
+ * when called is just peeking, we can simply call function for
+ * single thread, as it will not modify no data, and will not cause
+ * deadlock
+ */
+
+ pthread_mutex_lock(&rb->lock);
+ count = rb_recvs(rb, buffer, count, flags);
+ pthread_mutex_unlock(&rb->lock);
+ }
+ else
+ {
+ count = rb_recvt(rb, buffer, count, flags);
+ }
pthread_mutex_lock(&rb->lock);
rb->tinread--;
diff --git a/rb/tests.c b/rb/tests.c
index d9592f7..1f779dd 100644
--- a/rb/tests.c
+++ b/rb/tests.c
@@ -156,7 +156,17 @@ static void multi_producers_consumers(void)
/*
* wait until all indexes has been consumed
*/
- while (multi_index_count < sizeof(data)/sizeof(*data));
+ while (multi_index_count < sizeof(data)/sizeof(*data))
+ {
+ int buf[16];
+
+ /*
+ * while waiting, we randomly peek into rb, and to make sure,
+ * peeking won't make a difference
+ */
+
+ rb_recv(rb, buf, rand() % 16, MSG_PEEK);
+ }
rb_destroy(rb);
@@ -245,8 +255,42 @@ static void multi_thread(void)
free(send_buf);
free(recv_buf);
}
+
#endif
+static void peeking(void)
+{
+ struct rb *rb;
+ int v[8];
+ int d[8];
+ int i;
+
+ for (i = 0; i != sizeof(v)/sizeof(*v); ++i)
+ {
+ d[i] = i;
+ }
+
+ memset(v, 0, sizeof(v));
+ mt_assert(rb = rb_new(8, sizeof(int), 0));
+
+ rb_write(rb, d, 4);
+ rb_recv(rb, v, 2, MSG_PEEK);
+ mt_fail(v[0] == 0);
+ mt_fail(v[1] == 1);
+ mt_fail(v[2] == 0);
+ mt_fail(v[3] == 0);
+ memset(v, 0, sizeof(v));
+ rb_recv(rb, v, 6, MSG_PEEK);
+ mt_fail(v[0] == 0);
+ mt_fail(v[1] == 1);
+ mt_fail(v[2] == 2);
+ mt_fail(v[3] == 3);
+ mt_fail(v[4] == 0);
+ mt_fail(v[5] == 0);
+
+ rb_destroy(rb);
+}
+
static void single_thread(void)
{
size_t read;
@@ -363,5 +407,7 @@ int main(void)
}
}
+ mt_run(peeking);
+
mt_return();
}