diff --git a/m-buffer.h b/m-buffer.h index 38534245..245b77d6 100644 --- a/m-buffer.h +++ b/m-buffer.h @@ -50,6 +50,7 @@ typedef enum { BUFFER_DEFERRED_POP = 64 } buffer_policy_e; + /* Define a lock based buffer. USAGE: BUFFER_DEF(name, type, size_of_buffer_or_0, policy[, oplist]) */ #define BUFFER_DEF(name, type, m_size, ... ) \ @@ -59,13 +60,26 @@ typedef enum { (name, type, m_size,__VA_ARGS__, M_C(name,_t)))) \ M_END_PROTECTED_CODE + +/* Define a lock based buffer + as the provided type name_t. + USAGE: BUFFER_DEF_AS(name, name_t, type, size_of_buffer_or_0, policy[, oplist]) */ +#define BUFFER_DEF_AS(name, name_t, type, m_size, ... ) \ + M_BEGIN_PROTECTED_CODE \ + BUFFERI_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ + ((name, type, m_size,__VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \ + (name, type, m_size,__VA_ARGS__, name_t ))) \ + M_END_PROTECTED_CODE + + /* Define the oplist of a lock based buffer given its name and its oplist. USAGE: BUFFER_OPLIST(name[, oplist of the type]) */ #define BUFFER_OPLIST(...) \ BUFFERI_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ - ((__VA_ARGS__, M_DEFAULT_OPLIST), \ + ((__VA_ARGS__, M_DEFAULT_OPLIST), \ (__VA_ARGS__ ))) + /* Define a nearly lock-free queue for Many Producer Many Consummer Much faster than queue of BUFFER_DEF in heavy communication scenario Size of created queue can only a power of 2. @@ -77,6 +91,20 @@ typedef enum { (name, type, __VA_ARGS__, M_C(name,_t)))) \ M_END_PROTECTED_CODE + +/* Define a nearly lock-free queue for Many Producer Many Consummer + as the provided type name_t. + Much faster than queue of BUFFER_DEF in heavy communication scenario + Size of created queue can only a power of 2. +*/ +#define QUEUE_MPMC_DEF_AS(name, name_t, type, ...) \ + M_BEGIN_PROTECTED_CODE \ + QUEUEI_MPMC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ + ((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \ + (name, type, __VA_ARGS__, name_t ))) \ + M_END_PROTECTED_CODE + + /* Define a wait-free queue for Single Producer Single Consummer Much faster than queue of BUFFER_DEF in heavy communication scenario Size of created queue can only a power of 2. @@ -89,6 +117,19 @@ typedef enum { M_END_PROTECTED_CODE +/* Define a wait-free queue for Single Producer Single Consummer + as the provided type name_t. + Much faster than queue of BUFFER_DEF in heavy communication scenario + Size of created queue can only a power of 2. +*/ +#define QUEUE_SPSC_DEF_AS(name, name_t, type, ...) \ + M_BEGIN_PROTECTED_CODE \ + QUEUEI_SPSC_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ + ((name, type, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \ + (name, type, __VA_ARGS__, name_t ))) \ + M_END_PROTECTED_CODE + + /********************************** INTERNAL ************************************/ diff --git a/tests/test-mbuffer.c b/tests/test-mbuffer.c index bf131003..0cc60e2d 100644 --- a/tests/test-mbuffer.c +++ b/tests/test-mbuffer.c @@ -45,6 +45,14 @@ BUFFER_DEF(buffer_mpz, testobj_t, 32, BUFFER_QUEUE, TESTOBJ_OPLIST) QUEUE_MPMC_DEF(queue_z, testobj_t, BUFFER_QUEUE, TESTOBJ_OPLIST) QUEUE_SPSC_DEF(squeue_a, testobj_t, BUFFER_QUEUE, TESTOBJ_OPLIST) +// Define other buffers +BUFFER_DEF_AS(BufferDouble1, BufferDouble1, double, 4, BUFFER_QUEUE) +QUEUE_MPMC_DEF_AS(BufferDouble2, BufferDouble2, double, BUFFER_QUEUE) +QUEUE_SPSC_DEF_AS(BufferDouble3, BufferDouble3, double, BUFFER_QUEUE) +#define M_OPL_BufferDouble1() BUFFER_OPLIST(BufferDouble1, M_DEFAULT_OPLIST) +#define M_OPL_BufferDouble2() BUFFER_OPLIST(BufferDouble2, M_DEFAULT_OPLIST) +#define M_OPL_BufferDouble3() BUFFER_OPLIST(BufferDouble3, M_DEFAULT_OPLIST) + buffer_uint_t g_buff; buffer_uint_t g_buffB; @@ -507,7 +515,65 @@ static void test_spsc(void) /********************************************************************************************/ -int main(void) +static void test_double1(void) +{ + bool b; + M_LET(buffer, BufferDouble1) { + b = BufferDouble1_push(buffer, 0.0); + assert(b); + b= BufferDouble1_push(buffer, 1.0); + assert(b); + double d; + b = BufferDouble1_pop(&d, buffer); + assert(b); + assert(d == 0.0); + b = BufferDouble1_pop(&d, buffer); + assert(b); + assert(d == 1.0); + } +} + +static void test_double2(void) +{ + bool b; + BufferDouble2 buffer; + BufferDouble2_init(buffer, 2); + b = BufferDouble2_push(buffer, 0.0); + assert(b); + b= BufferDouble2_push(buffer, 1.0); + assert(b); + double d; + b = BufferDouble2_pop(&d, buffer); + assert(b); + assert(d == 0.0); + b = BufferDouble2_pop(&d, buffer); + assert(b); + assert(d == 1.0); + BufferDouble2_clear(buffer); +} + +static void test_double3(void) +{ + bool b; + BufferDouble3 buffer; + BufferDouble3_init(buffer, 2); + b = BufferDouble3_push(buffer, 0.0); + assert(b); + b= BufferDouble3_push(buffer, 1.0); + assert(b); + double d; + b = BufferDouble3_pop(&d, buffer); + assert(b); + assert(d == 0.0); + b = BufferDouble3_pop(&d, buffer); + assert(b); + assert(d == 1.0); + BufferDouble3_clear(buffer); +} + +/********************************************************************************************/ + +static void test_uint(void) { unsigned int x, y; buffer_uint_t v; @@ -529,7 +595,11 @@ int main(void) assert (y == 10); buffer_uint_clear(v); +} +int main(void) +{ + test_uint(); test_global(); test_stack(); test_stack2(); @@ -537,5 +607,8 @@ int main(void) test_global_ishared(); test_queue(1000000, 2, 2148371710223136ULL); test_spsc(); + test_double1(); + test_double2(); + test_double3(); exit(0); }