diff options
author | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2018-01-14 20:10:17 +0100 |
---|---|---|
committer | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2018-01-14 20:56:04 +0100 |
commit | cebe52e4ccac463a25f989af01d75b6b7cf65727 (patch) | |
tree | b04844e599f5ca633e2e4bd0ccb17186fb65c693 /rb | |
parent | f65d8a06e55882a93f226c96f237921f28169547 (diff) | |
download | librb-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.h | 53 | ||||
-rw-r--r-- | rb/rb.c | 17 | ||||
-rw-r--r-- | rb/tests.c | 48 |
3 files changed, 108 insertions, 10 deletions
@@ -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 ========================================================================== */ @@ -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--; @@ -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(); } |