From ed364de0e13fcb70d890ffa3763e7c7ec5a5797b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Tue, 12 Jan 2010 12:53:12 +0100 Subject: rename ring_buffer to ringbuffer and remove previous attempt --- Makefile | 15 ++-- lf_ring_buffer.c | 174 -------------------------------------------- lf_ring_buffer.h | 73 ------------------- lf_ring_buffer2.c | 181 ---------------------------------------------- lf_ring_buffer2.h | 73 ------------------- lf_ring_buffer_data.h | 20 ------ lf_ring_buffer_test.c | 191 ------------------------------------------------- lf_ring_buffer_test2.c | 191 ------------------------------------------------- lf_ringbuffer.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++ lf_ringbuffer.h | 73 +++++++++++++++++++ lf_ringbuffer_data.h | 20 ++++++ lf_ringbuffer_test.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 470 insertions(+), 913 deletions(-) delete mode 100644 lf_ring_buffer.c delete mode 100644 lf_ring_buffer.h delete mode 100644 lf_ring_buffer2.c delete mode 100644 lf_ring_buffer2.h delete mode 100644 lf_ring_buffer_data.h delete mode 100644 lf_ring_buffer_test.c delete mode 100644 lf_ring_buffer_test2.c create mode 100644 lf_ringbuffer.c create mode 100644 lf_ringbuffer.h create mode 100644 lf_ringbuffer_data.h create mode 100644 lf_ringbuffer_test.c diff --git a/Makefile b/Makefile index 79b79ab..38ab176 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC = gcc STD = _GNU_SOURCE CFLAGS = -DDEBUG -BIN = cas container_of lock_free_queue_test lf_fifo_test lf_ring_buffer_test lf_ring_buffer_test2 +BIN = cas container_of lock_free_queue_test lf_fifo_test lf_ringbuffer_test .c.o: $(CC) -march=i686 -O2 -c -Wall -I. $(CFLAGS) -D$(STD) $< @@ -30,15 +30,10 @@ lf_fifo_test.o: lf_fifo_test.c lf_fifo_test: lf_fifo.o lf_fifo_test.o $(CC) lf_fifo.o lf_fifo_test.o -o lf_fifo_test -lf_ring_buffer.o: lf_ring_buffer.h lf_ring_buffer.c lf_ring_buffer_data.h lf_portable_cas.h -lf_ring_buffer_test.o: lf_ring_buffer_test.c -lf_ring_buffer_test: lf_ring_buffer.o lf_ring_buffer_test.o - $(CC) -lrt lf_ring_buffer.o lf_ring_buffer_test.o -o lf_ring_buffer_test - -lf_ring_buffer2.o: lf_ring_buffer2.h lf_ring_buffer2.c lf_ring_buffer_data.h lf_portable_cas.h -lf_ring_buffer_test2.o: lf_ring_buffer_test2.c -lf_ring_buffer_test2: lf_ring_buffer2.o lf_ring_buffer_test2.o - $(CC) -lrt lf_ring_buffer2.o lf_ring_buffer_test2.o -o lf_ring_buffer_test2 +lf_ringbuffer.o: lf_ringbuffer.h lf_ringbuffer.c lf_ringbuffer_data.h lf_portable_cas.h +lf_ringbuffer_test.o: lf_ringbuffer_test.c lf_ringbuffer.h +lf_ringbuffer_test: lf_ringbuffer.o lf_ringbuffer_test.o + $(CC) -lrt lf_ringbuffer.o lf_ringbuffer_test.o -o lf_ringbuffer_test clean: rm -f *~ *.o *.s core $(BIN) diff --git a/lf_ring_buffer.c b/lf_ring_buffer.c deleted file mode 100644 index 606e29a..0000000 --- a/lf_ring_buffer.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * File : lf_ring_buffer.c - * Author : Jérémy Zurcher - * Date : 05/01/010 - * License : - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "lf_ring_buffer.h" -#include "lf_portable_cas.h" -#include -#include -#include - -//#define DEBUG_LFRB_KO 1 -//#define DEBUG_LFRB_CAS 1 -//#define DEBUG_LFRB 1 - -#ifdef DEBUG_LFRB - #include - #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) - #define _LOG_CAS_( ... ) fprintf(stdout,__VA_ARGS__) -#elif defined DEBUG_LFRB_CAS - #include - #define _LOG_KO_( ... ) - #define _LOG_CAS_( ... ) fprintf(stdout,__VA_ARGS__) -#elif defined DEBUG_LFRB_KO - #include - #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) - #define _LOG_CAS_( ... ) -#else - #define _LOG_KO_( ... ) - #define _LOG_CAS_( ... ) -#endif - -#define BACKOFF_NANO_SLEEP 100000 - -/* initialize an empty lf_ring_buffer struct */ -lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ) { - /* alloc ring_buffer struct */ - lf_ring_buffer_t *r = malloc(sizeof(lf_ring_buffer_t)); - if(r==NULL) return NULL; - /* */ - r->buffer = malloc(LFRB_BUFFER_SIZE*n_buf); - if(r->buffer==NULL) { - free(r); - return NULL; - } - memset(r->buffer,0,LFRB_BUFFER_SIZE*n_buf); - r->n_buf = n_buf; - r->read_from = -1; - r->write_to = 0; - return r; -} - -/* destroy an lf_ring_buffer strcture */ -void lf_ring_buffer_destroy( lf_ring_buffer_t *r ) { - free(r->buffer); - free(r); -} - -/* return 1 if is empty */ -int lf_ring_buffer_empty( lf_ring_buffer_t *r ) { return r->read_from==-1; } - -/* write data into the ring buffer */ -int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ) { - int write_to, read_from, next; - struct timespec backoff; - int backoff_time = BACKOFF_NANO_SLEEP; - /* reserve a buffer */ - for(;;){ - write_to = r->write_to; - read_from = r->read_from; - if(LFRB_IS_AVAILABLE( r->buffer[write_to] ) ) { - /* read_from==write_to means that the buffer is full and that a writer thread which at first reserved this buffer - * hasn't had enough CPU cycles to call MARK_AS_FILLED - */ - if( read_from!=write_to ) { - next = write_to+1; - if (next==r->n_buf) next=0; - /* what might have happend between IS_AVAILABLE and now : - * - a writter has reserved this buffer => write_to has moved => CAS fails - * - a reader has consumed a buffer => read_from has moved => we've got more space - */ - _LOG_CAS_( "write: CAS %d %d %d\n", r->write_to, write_to, next ); - if( CompareAndSwapInt( &r->write_to, write_to, next ) ) { - /* !!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!! - * - if the ring is empty before this write operation (r->read_from==-1 or latest idx) - * - and n_buf other threads execute this same function before the next CAS is finished - * then, the last thread will : - * - see this buffer as available - * - and see the ring as empty instead of full !!!!! - * so it will ends with two threads writing on this buffer - */ - if(r->read_from==-1) CompareAndSwapInt( &r->read_from, -1, write_to ); - break; - } - } else { - _LOG_KO_("write: ring full %d %d\n",r->read_from,idx); - if(IS_NOT_BLOCKING(flags)) return -1; - backoff.tv_sec = 0; - backoff.tv_nsec = backoff_time; - nanosleep(&backoff,NULL); - } - } else { - _LOG_KO_("write: buffer not available\n"); - if(IS_NOT_BLOCKING(flags)) return -1; - backoff.tv_sec = 0; - backoff.tv_nsec = backoff_time; - nanosleep(&backoff,NULL); - } - backoff_time += BACKOFF_NANO_SLEEP; - } - /* fill this buffer and mark it as filled */ - memcpy( LFRB_DATA_PTR(r->buffer[write_to]), data, LFRB_DATA_SIZE ); - LFRB_MARK_AS_FILLED( r->buffer[write_to] ); - return 0; -} - -/* read data from the ring buffer */ -int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ) { - int write_to, read_from, next; - struct timespec backoff; - int backoff_time = BACKOFF_NANO_SLEEP; - for(;;) { - write_to = r->write_to; - read_from = r->read_from; - if( !(LFRB_IS_AVAILABLE( r->buffer[read_from] )) && read_from!=-1 ) { - next = read_from+1; - if (next==r->n_buf) next=0; - /* will do bad things if data dst buffer is too small !! */ - memcpy( data, LFRB_DATA_PTR(r->buffer[read_from]), LFRB_DATA_SIZE ); - _LOG_CAS_( "read: CAS %d %d %d\n", r->read_from, read_from, next ); - if( CompareAndSwapInt( &r->read_from, read_from, next ) ) { - if(r->read_from==r->write_to) { - /* the buffer is empty but writers will see it as full */ - _LOG_CAS_( "read: empty CAS %d %d %d\n", r->read_from, next, -1 ); - CompareAndSwapInt( &r->read_from, next, -1 ); - } - break; - } - } - - _LOG_KO_("read: ring empty\n"); - if(IS_NOT_BLOCKING(flags)) return -1; - backoff.tv_sec = 0; - backoff.tv_nsec = backoff_time; - nanosleep(&backoff,NULL); - backoff_time += BACKOFF_NANO_SLEEP; - } - /* finish the read process */ - LFRB_MARK_AS_READ( r->buffer[read_from] ); - return 0; -} - diff --git a/lf_ring_buffer.h b/lf_ring_buffer.h deleted file mode 100644 index 14a1aec..0000000 --- a/lf_ring_buffer.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * File : lf_ring_buffer.h - * Author : Jérémy Zurcher - * Date : 05/01/010 - * License : - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _LF_RING_BUFFER_H_ -#define _LF_RING_BUFFER_H_ - -# ifdef __cplusplus -extern "C" { -# endif /* __cplusplus */ - -#include -#include "lf_ring_buffer_data.h" - -#define LFRB_NO_BLOCK 1 /* if buffer is full, leave instead of try again and again */ -#define IS_NOT_BLOCKING( flags ) ( (flags)&LFRB_NO_BLOCK ) - -typedef struct ring_buffer { - LFRB_BUFFER_TYPE *buffer; /* buffer data */ - size_t n_buf; /* number of buffers */ - int read_from; /* index where to read data from */ - int write_to; /* index where to write data to */ -} lf_ring_buffer_t; - -/* return an initialized lf_ring_buffer_t struct */ -lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ); - -/* destroy an lf_ring_buffer_t struct */ -void lf_ring_buffer_destroy( lf_ring_buffer_t *r ); - -/* return 1 if is empty */ -int lf_ring_buffer_empty( lf_ring_buffer_t *r ); - -/* write data into the ring buffer - * return 0 on success - * return -1 if IS_NOT_BLOCKING and buffer is full - */ -int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ); - -/* read data from the ring buffer - * return 0 on success - * return -1 if IS_NOT_BLOCKING and buffer is empty - */ -int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ); - -# ifdef __cplusplus -} -# endif /* __cplusplus */ - -# endif /* _LF_RING_BUFFER_H_ */ diff --git a/lf_ring_buffer2.c b/lf_ring_buffer2.c deleted file mode 100644 index 4a1a3cd..0000000 --- a/lf_ring_buffer2.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * File : lf_ring_buffer.c - * Author : Jérémy Zurcher - * Date : 05/01/010 - * License : - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "lf_ring_buffer2.h" -#include "lf_portable_cas.h" -#include -#include -#include - -//#define DEBUG_LFRB_KO 1 -//#define DEBUG_LFRB_CAS 1 -//#define DEBUG_LFRB 1 - -#ifdef DEBUG_LFRB - #include - #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) - #define _LOG_CAS_( ... )fprintf(stdout,__VA_ARGS__) -#elif defined DEBUG_LFRB_CAS - #include - #define _LOG_KO_( ... ) - #define _LOG_CAS_( ... )fprintf(stdout,__VA_ARGS__) -#elif defined DEBUG_LFRB_KO - #include - #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) - #define _LOG_CAS_( ... ) -#else - #define _LOG_KO_( ... ) - #define _LOG_CAS_( ... ) -#endif - -#define BACKOFF_NANO_SLEEP 10 - -#define USHORTMAX 0xffff - -/* An unsigned int (indexes) is used to store both read_from and write_to indexes - * so that 32 bits compare and swap may be used to update both in one atomic instruction call. - * To be able to differenciate an empty buffer from a full buffer, - * read_from part of indexes is set to 0xffff (USHORTMAX) when the buffer is empty. - * Thus the maximum size of the buffer is 0xffff-1 = 65534 elements - */ - -/* initialize an empty lf_ring_buffer struct */ -lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ) { - if(n_buf>=USHORTMAX) { - return NULL; - } - /* alloc ring_buffer struct */ - lf_ring_buffer_t *r = malloc(sizeof(lf_ring_buffer_t)); - if(r==NULL) return NULL; - /* alloc buffer */ - r->buffer = malloc(LFRB_BUFFER_SIZE*n_buf); - if(r->buffer==NULL) { - free(r); - return NULL; - } - memset(r->buffer,0,LFRB_BUFFER_SIZE*n_buf); - r->n_buf = n_buf; - r->indexes = (unsigned int)(USHORTMAX<<16) | (unsigned int)0; - return r; -} - -/* destroy an lf_ring_buffer strcture */ -void lf_ring_buffer_destroy( lf_ring_buffer_t *r ) { - free(r->buffer); - free(r); -} - -/* return 1 if is empty */ -int lf_ring_buffer_empty( lf_ring_buffer_t *r ) { return (r->indexes>>16)==USHORTMAX; } - -/* write data into the ring buffer */ -int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ) { - unsigned int current, next; - unsigned int write_to, read_from; - struct timespec backoff; - int backoff_time = BACKOFF_NANO_SLEEP; - /* reserve a buffer */ - for(;;){ - /* copy indexes and split it */ - current = r->indexes; - write_to = current&0xffff; - read_from = current>>16; - /* - * check if the buffer is available, - * if read_from==write_to the buffer is full - * if it is available and full, it means that a writer thread which reserved this buffer - * hadn't had enough CPU cycles to call MARK_AS_FILLED - */ - if( LFRB_IS_AVAILABLE( r->buffer[write_to] ) && read_from!=write_to ) { - next = write_to+1; - if (next==r->n_buf) next=0; - /* set read_from to write_to if needed */ - if (read_from==USHORTMAX) { - next |= write_to<<16; - } else { - next |= read_from<<16; - } - /* try to update indexes */ - _LOG_CAS_( "write: CAS %u %u %u\n", r->indexes, current, next ); - if( CompareAndSwapInt( &r->indexes, current, next ) ) break; - } else { - _LOG_KO_("write: impossible : wt:%d rf:%d wa:%d\n",write_to,read_from,LFRB_IS_AVAILABLE(r->buffer[write_to])); - if(IS_NOT_BLOCKING(flags)) return -1; - } - /* sleep */ - backoff.tv_sec = 0; - backoff.tv_nsec = backoff_time; - nanosleep(&backoff,NULL); - backoff_time += BACKOFF_NANO_SLEEP; - } - /* fill this buffer and mark it as filled */ - memcpy( LFRB_DATA_PTR(r->buffer[write_to]), data, LFRB_DATA_SIZE ); - LFRB_MARK_AS_FILLED( r->buffer[write_to] ); - return 0; -} - -/* read data from the ring buffer */ -int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ) { - unsigned int current, next; - unsigned int write_to, read_from, tmp; - struct timespec backoff; - int backoff_time = BACKOFF_NANO_SLEEP; - for(;;) { - /* copy indexes and split it */ - current = r->indexes; - write_to = current&0xffff; - read_from = current>>16; - /* - * the buffer may be non empty but available if a writer thread hadn't had enough CPU cycles to mark the buffer as filled - */ - if( read_from==USHORTMAX || LFRB_IS_AVAILABLE( r->buffer[read_from] ) ) { - _LOG_KO_("read : impossible : wt:%d rf:%d ra:%d\n",write_to,read_from,LFRB_IS_AVAILABLE(r->buffer[read_from])); - if(IS_NOT_BLOCKING(flags)) return -1; - } else { - tmp = read_from +1; - if (tmp==r->n_buf) tmp=0; - /* set the buffer empty if needed */ - if (tmp==write_to) { - tmp = USHORTMAX; - } - next = tmp<<16 | write_to; - /* try to update indexes */ - _LOG_CAS_( "read: CAS %u %u %u\n", r->indexes, current, next ); - if( CompareAndSwapInt( &r->indexes, current , next ) ) break; - } - /* sleep */ - backoff.tv_sec = 0; - backoff.tv_nsec = backoff_time; - nanosleep(&backoff,NULL); - backoff_time += BACKOFF_NANO_SLEEP; - } - /* copy this buffer and mark it as read */ - memcpy( data, LFRB_DATA_PTR(r->buffer[read_from]), LFRB_DATA_SIZE ); - LFRB_MARK_AS_READ( r->buffer[read_from] ); - return 0; -} - diff --git a/lf_ring_buffer2.h b/lf_ring_buffer2.h deleted file mode 100644 index acf9974..0000000 --- a/lf_ring_buffer2.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * File : lf_ring_buffer.h - * Author : Jérémy Zurcher - * Date : 05/01/010 - * License : - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _LF_RING_BUFFER_H_ -#define _LF_RING_BUFFER_H_ - -# ifdef __cplusplus -extern "C" { -# endif /* __cplusplus */ - -#include -#include "lf_ring_buffer_data.h" - -#define LFRB_NO_BLOCK 1 /* if buffer is full, leave instead of try again and again */ -#define IS_NOT_BLOCKING( flags ) ( (flags)&LFRB_NO_BLOCK ) - -/* the ring buffer structure */ -typedef struct ring_buffer { - LFRB_BUFFER_TYPE *buffer; /* buffer data */ - size_t n_buf; /* number of buffers, max 65534, see implementation for details */ - unsigned int indexes; /* indexes where to read_from and write_to */ -} lf_ring_buffer_t; - -/* return an initialized lf_ring_buffer_t struct, size is limited to 65534, see implementation for details */ -lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ); - -/* destroy an lf_ring_buffer_t struct */ -void lf_ring_buffer_destroy( lf_ring_buffer_t *r ); - -/* return 1 if is empty */ -int lf_ring_buffer_empty( lf_ring_buffer_t *r ); - -/* write data into the ring buffer - * return 0 on success - * return -1 if IS_NOT_BLOCKING and buffer is full - */ -int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ); - -/* read data from the ring buffer - * return 0 on success - * return -1 if IS_NOT_BLOCKING and buffer is empty - */ -int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ); - -# ifdef __cplusplus -} -# endif /* __cplusplus */ - -# endif /* _LF_RING_BUFFER_H_ */ diff --git a/lf_ring_buffer_data.h b/lf_ring_buffer_data.h deleted file mode 100644 index 80092d5..0000000 --- a/lf_ring_buffer_data.h +++ /dev/null @@ -1,20 +0,0 @@ - -typedef char rb_data_t; - -#define RB_DATA_LEN 24 - -typedef struct buffer { - char status; - rb_data_t data[RB_DATA_LEN]; -} rb_buffer_t; - -#define LFRB_DATA_SIZE ( sizeof(rb_data_t)*RB_DATA_LEN ) - -#define LFRB_BUFFER_TYPE rb_buffer_t -#define LFRB_BUFFER_SIZE ( sizeof(rb_buffer_t) ) - -#define LFRB_IS_AVAILABLE( el ) (el.status==0) -#define LFRB_MARK_AS_FILLED( el ) { (el).status=1; } -#define LFRB_MARK_AS_READ( el ) { (el).status=0; } -#define LFRB_DATA_PTR( el ) (el).data - diff --git a/lf_ring_buffer_test.c b/lf_ring_buffer_test.c deleted file mode 100644 index 2f95af1..0000000 --- a/lf_ring_buffer_test.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include -#include - -#include "lf_ring_buffer.h" - -#define BUFFER_LEN 5000000 - -//static rb_data_t data[BUFFER_LEN][RB_DATA_LEN]; - -static int64_t time_diff(struct timespec *t0, struct timespec *t1) -{ - return ((t1->tv_sec * 1000000000) + t1->tv_nsec) - ((t0->tv_sec * 1000000000) + t0->tv_nsec); -} - -/* -static void print_now(char* s) { - fprintf(stdout,s); - fflush(stdout); -} -*/ - -static void report( char* op, int n, uint64_t dt, int redo ) { - fprintf(stdout,"\t%9d %s operations in %4d [ms] => %7d [us] => %10d [ns]\t >>> %6d [ns/op]\t%4d redone operations\n", - n, op, (int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/n), redo ); -} - -struct thread_params { - lf_ring_buffer_t *ring; - int n; - int flags; - uint64_t dt; -}; - -/* -static void feed_data( int n){ - int i; - for(i=0; in, sequential_writes( params->ring, params->n, params->flags ) ); - params->dt = sequential_writes( params->ring, params->n, params->flags ); - return NULL; -} - -void* reader_thread( void* param ) { - struct thread_params *params = (struct thread_params*)param; - //report( "read ", params->n, sequential_reads( params->ring, params->n, params->flags ) ); - params->dt = sequential_reads( params->ring, params->n, params->flags ); - return NULL; -} - -static void parallel_op( int op, int nt, lf_ring_buffer_t *ring, int n, int flags ) { - int i; - uint64_t dt; - - pthread_t *threads = malloc( sizeof(pthread_t)*nt); - struct thread_params *params = malloc( sizeof(struct thread_params)*nt); - - for(i=0; i %7d [us] => %10d [ns]\t >>> %6d [ns/op]\n",(int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/(n/nt)) ); - /* empty the ring */ - free(threads); - free(params); -} - -int main( int argc, char** argv ) { - - int i; - int b_len = BUFFER_LEN; - lf_ring_buffer_t *ring; - - ring = lf_ring_buffer_create( b_len ); - if(ring==NULL){ - fprintf(stderr,"ERROR : lf_ring_buffer_create( %d );\n",b_len); - exit( EXIT_FAILURE ); - } - - /* - print_now("feed the data ... "); - feed_data(b_len); - printf("done.\n"); - */ - - printf("sequential non blocking write operations ...\n"); - sequential_writes( ring, b_len, 0 ); - printf("sequential non blocking read operations ...\n"); - sequential_reads( ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - printf("sequential blocking write operations ...\n"); - sequential_writes( ring, b_len, LFRB_NO_BLOCK ); - printf("sequential blocking read operations ...\n"); - sequential_reads( ring, b_len, LFRB_NO_BLOCK ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - - for(i=5; i<=100;i*=2) { - printf("%d parallel blocking with backoff inc write operations .... \n",i); - parallel_op( 0, i, ring, b_len, 0 ); - printf("parallel blocking read operations ...\n"); - sequential_reads( ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - for(i=5; i<=100;i*=2) { - printf("%d parallel non blocking write operations .... \n",i); - parallel_op( 0, i, ring, b_len, LFRB_NO_BLOCK ); - printf("non blocking read operations ...\n"); - sequential_reads( ring, b_len, LFRB_NO_BLOCK ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - for(i=10; i<=100;i*=2) { - printf("%d parallel blocking write and read operations .... \n",i*2); - parallel_op( 3, i, ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - - lf_ring_buffer_destroy( ring ); - - return EXIT_SUCCESS; -} - diff --git a/lf_ring_buffer_test2.c b/lf_ring_buffer_test2.c deleted file mode 100644 index c1288cc..0000000 --- a/lf_ring_buffer_test2.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include -#include - -#include "lf_ring_buffer2.h" - -#define BUFFER_LEN 65000 - -//static rb_data_t data[BUFFER_LEN][RB_DATA_LEN]; - -static int64_t time_diff(struct timespec *t0, struct timespec *t1) -{ - return ((t1->tv_sec * 1000000000) + t1->tv_nsec) - ((t0->tv_sec * 1000000000) + t0->tv_nsec); -} - -/* -static void print_now(char* s) { - fprintf(stdout,s); - fflush(stdout); -} -*/ - -static void report( char* op, int n, uint64_t dt, int redo ) { - fprintf(stdout,"\t%9d %s operations in %4d [ms] => %7d [us] => %10d [ns]\t >>> %6d [ns/op]\t%4d redone operations\n", - n, op, (int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/n), redo ); -} - -struct thread_params { - lf_ring_buffer_t *ring; - int n; - int flags; - uint64_t dt; -}; - -/* -static void feed_data( int n){ - int i; - for(i=0; in, sequential_writes( params->ring, params->n, params->flags ) ); - params->dt = sequential_writes( params->ring, params->n, params->flags ); - return NULL; -} - -void* reader_thread( void* param ) { - struct thread_params *params = (struct thread_params*)param; - //report( "read ", params->n, sequential_reads( params->ring, params->n, params->flags ) ); - params->dt = sequential_reads( params->ring, params->n, params->flags ); - return NULL; -} - -static void parallel_op( int op, int nt, lf_ring_buffer_t *ring, int n, int flags ) { - int i; - uint64_t dt; - - pthread_t *threads = malloc( sizeof(pthread_t)*nt); - struct thread_params *params = malloc( sizeof(struct thread_params)*nt); - - for(i=0; i %7d [us] => %10d [ns]\t >>> %6d [ns/op]\n",(int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/(n/nt)) ); - /* empty the ring */ - free(threads); - free(params); -} - -int main( int argc, char** argv ) { - - int i; - int b_len = BUFFER_LEN; - lf_ring_buffer_t *ring; - - ring = lf_ring_buffer_create( b_len ); - if(ring==NULL){ - fprintf(stderr,"ERROR : lf_ring_buffer_create( %d );\n",b_len); - exit( EXIT_FAILURE ); - } - - /* - print_now("feed the data ... "); - feed_data(b_len); - printf("done.\n"); - */ - - printf("sequential non blocking write operations ...\n"); - sequential_writes( ring, b_len, 0 ); - printf("sequential non blocking read operations ...\n"); - sequential_reads( ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - printf("sequential blocking write operations ...\n"); - sequential_writes( ring, b_len, LFRB_NO_BLOCK ); - printf("sequential blocking read operations ...\n"); - sequential_reads( ring, b_len, LFRB_NO_BLOCK ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - - for(i=5; i<=50;i*=2) { - printf("%d parallel blocking with backoff inc write operations .... \n",i); - parallel_op( 0, i, ring, b_len, 0 ); - printf("parallel blocking read operations ...\n"); - sequential_reads( ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - for(i=5; i<=50;i*=2) { - printf("%d parallel non blocking write operations .... \n",i); - parallel_op( 0, i, ring, b_len, LFRB_NO_BLOCK ); - printf("non blocking read operations ...\n"); - sequential_reads( ring, b_len, LFRB_NO_BLOCK ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - for(i=10; i<=50;i*=2) { - printf("%d parallel blocking write and read operations .... \n",i*2); - parallel_op( 3, i, ring, b_len, 0 ); - if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } - } - - lf_ring_buffer_destroy( ring ); - - return EXIT_SUCCESS; -} - diff --git a/lf_ringbuffer.c b/lf_ringbuffer.c new file mode 100644 index 0000000..99b8766 --- /dev/null +++ b/lf_ringbuffer.c @@ -0,0 +1,181 @@ +/* + * File : lf_ring_buffer.c + * Author : Jérémy Zurcher + * Date : 05/01/010 + * License : + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "lf_ringbuffer.h" +#include "lf_portable_cas.h" +#include +#include +#include + +//#define DEBUG_LFRB_KO 1 +//#define DEBUG_LFRB_CAS 1 +//#define DEBUG_LFRB 1 + +#ifdef DEBUG_LFRB + #include + #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) + #define _LOG_CAS_( ... )fprintf(stdout,__VA_ARGS__) +#elif defined DEBUG_LFRB_CAS + #include + #define _LOG_KO_( ... ) + #define _LOG_CAS_( ... )fprintf(stdout,__VA_ARGS__) +#elif defined DEBUG_LFRB_KO + #include + #define _LOG_KO_( ... ) fprintf(stdout,__VA_ARGS__) + #define _LOG_CAS_( ... ) +#else + #define _LOG_KO_( ... ) + #define _LOG_CAS_( ... ) +#endif + +#define BACKOFF_NANO_SLEEP 10 + +#define USHORTMAX 0xffff + +/* An unsigned int (indexes) is used to store both read_from and write_to indexes + * so that 32 bits compare and swap may be used to update both in one atomic instruction call. + * To be able to differenciate an empty buffer from a full buffer, + * read_from part of indexes is set to 0xffff (USHORTMAX) when the buffer is empty. + * Thus the maximum size of the buffer is 0xffff-1 = 65534 elements + */ + +/* initialize an empty lf_ring_buffer struct */ +lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ) { + if(n_buf>=USHORTMAX) { + return NULL; + } + /* alloc ring_buffer struct */ + lf_ring_buffer_t *r = malloc(sizeof(lf_ring_buffer_t)); + if(r==NULL) return NULL; + /* alloc buffer */ + r->buffer = malloc(LFRB_BUFFER_SIZE*n_buf); + if(r->buffer==NULL) { + free(r); + return NULL; + } + memset(r->buffer,0,LFRB_BUFFER_SIZE*n_buf); + r->n_buf = n_buf; + r->indexes = (unsigned int)(USHORTMAX<<16) | (unsigned int)0; + return r; +} + +/* destroy an lf_ring_buffer strcture */ +void lf_ring_buffer_destroy( lf_ring_buffer_t *r ) { + free(r->buffer); + free(r); +} + +/* return 1 if is empty */ +int lf_ring_buffer_empty( lf_ring_buffer_t *r ) { return (r->indexes>>16)==USHORTMAX; } + +/* write data into the ring buffer */ +int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ) { + unsigned int current, next; + unsigned int write_to, read_from; + struct timespec backoff; + int backoff_time = BACKOFF_NANO_SLEEP; + /* reserve a buffer */ + for(;;){ + /* copy indexes and split it */ + current = r->indexes; + write_to = current&0xffff; + read_from = current>>16; + /* + * check if the buffer is available, + * if read_from==write_to the buffer is full + * if it is available and full, it means that a writer thread which reserved this buffer + * hadn't had enough CPU cycles to call MARK_AS_FILLED + */ + if( LFRB_IS_AVAILABLE( r->buffer[write_to] ) && read_from!=write_to ) { + next = write_to+1; + if (next==r->n_buf) next=0; + /* set read_from to write_to if needed */ + if (read_from==USHORTMAX) { + next |= write_to<<16; + } else { + next |= read_from<<16; + } + /* try to update indexes */ + _LOG_CAS_( "write: CAS %u %u %u\n", r->indexes, current, next ); + if( CompareAndSwapInt( &r->indexes, current, next ) ) break; + } else { + _LOG_KO_("write: impossible : wt:%d rf:%d wa:%d\n",write_to,read_from,LFRB_IS_AVAILABLE(r->buffer[write_to])); + if(IS_NOT_BLOCKING(flags)) return -1; + } + /* sleep */ + backoff.tv_sec = 0; + backoff.tv_nsec = backoff_time; + nanosleep(&backoff,NULL); + backoff_time += BACKOFF_NANO_SLEEP; + } + /* fill this buffer and mark it as filled */ + memcpy( LFRB_DATA_PTR(r->buffer[write_to]), data, LFRB_DATA_SIZE ); + LFRB_MARK_AS_FILLED( r->buffer[write_to] ); + return 0; +} + +/* read data from the ring buffer */ +int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ) { + unsigned int current, next; + unsigned int write_to, read_from, tmp; + struct timespec backoff; + int backoff_time = BACKOFF_NANO_SLEEP; + for(;;) { + /* copy indexes and split it */ + current = r->indexes; + write_to = current&0xffff; + read_from = current>>16; + /* + * the buffer may be non empty but available if a writer thread hadn't had enough CPU cycles to mark the buffer as filled + */ + if( read_from==USHORTMAX || LFRB_IS_AVAILABLE( r->buffer[read_from] ) ) { + _LOG_KO_("read : impossible : wt:%d rf:%d ra:%d\n",write_to,read_from,LFRB_IS_AVAILABLE(r->buffer[read_from])); + if(IS_NOT_BLOCKING(flags)) return -1; + } else { + tmp = read_from +1; + if (tmp==r->n_buf) tmp=0; + /* set the buffer empty if needed */ + if (tmp==write_to) { + tmp = USHORTMAX; + } + next = tmp<<16 | write_to; + /* try to update indexes */ + _LOG_CAS_( "read: CAS %u %u %u\n", r->indexes, current, next ); + if( CompareAndSwapInt( &r->indexes, current , next ) ) break; + } + /* sleep */ + backoff.tv_sec = 0; + backoff.tv_nsec = backoff_time; + nanosleep(&backoff,NULL); + backoff_time += BACKOFF_NANO_SLEEP; + } + /* copy this buffer and mark it as read */ + memcpy( data, LFRB_DATA_PTR(r->buffer[read_from]), LFRB_DATA_SIZE ); + LFRB_MARK_AS_READ( r->buffer[read_from] ); + return 0; +} + diff --git a/lf_ringbuffer.h b/lf_ringbuffer.h new file mode 100644 index 0000000..2266ba2 --- /dev/null +++ b/lf_ringbuffer.h @@ -0,0 +1,73 @@ +/* + * File : lf_ring_buffer.h + * Author : Jérémy Zurcher + * Date : 05/01/010 + * License : + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _LF_RING_BUFFER_H_ +#define _LF_RING_BUFFER_H_ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +#include +#include "lf_ringbuffer_data.h" + +#define LFRB_NO_BLOCK 1 /* if buffer is full, leave instead of try again and again */ +#define IS_NOT_BLOCKING( flags ) ( (flags)&LFRB_NO_BLOCK ) + +/* the ring buffer structure */ +typedef struct ring_buffer { + LFRB_BUFFER_TYPE *buffer; /* buffer data */ + size_t n_buf; /* number of buffers, max 65534, see implementation for details */ + unsigned int indexes; /* indexes where to read_from and write_to */ +} lf_ring_buffer_t; + +/* return an initialized lf_ring_buffer_t struct, size is limited to 65534, see implementation for details */ +lf_ring_buffer_t* lf_ring_buffer_create( size_t n_buf ); + +/* destroy an lf_ring_buffer_t struct */ +void lf_ring_buffer_destroy( lf_ring_buffer_t *r ); + +/* return 1 if is empty */ +int lf_ring_buffer_empty( lf_ring_buffer_t *r ); + +/* write data into the ring buffer + * return 0 on success + * return -1 if IS_NOT_BLOCKING and buffer is full + */ +int lf_ring_buffer_write( lf_ring_buffer_t *r, void *data, int flags ); + +/* read data from the ring buffer + * return 0 on success + * return -1 if IS_NOT_BLOCKING and buffer is empty + */ +int lf_ring_buffer_read( lf_ring_buffer_t *r, void *data, int flags ); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +# endif /* _LF_RING_BUFFER_H_ */ diff --git a/lf_ringbuffer_data.h b/lf_ringbuffer_data.h new file mode 100644 index 0000000..80092d5 --- /dev/null +++ b/lf_ringbuffer_data.h @@ -0,0 +1,20 @@ + +typedef char rb_data_t; + +#define RB_DATA_LEN 24 + +typedef struct buffer { + char status; + rb_data_t data[RB_DATA_LEN]; +} rb_buffer_t; + +#define LFRB_DATA_SIZE ( sizeof(rb_data_t)*RB_DATA_LEN ) + +#define LFRB_BUFFER_TYPE rb_buffer_t +#define LFRB_BUFFER_SIZE ( sizeof(rb_buffer_t) ) + +#define LFRB_IS_AVAILABLE( el ) (el.status==0) +#define LFRB_MARK_AS_FILLED( el ) { (el).status=1; } +#define LFRB_MARK_AS_READ( el ) { (el).status=0; } +#define LFRB_DATA_PTR( el ) (el).data + diff --git a/lf_ringbuffer_test.c b/lf_ringbuffer_test.c new file mode 100644 index 0000000..8c41b97 --- /dev/null +++ b/lf_ringbuffer_test.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include + +#include "lf_ringbuffer.h" + +#define BUFFER_LEN 65000 + +//static rb_data_t data[BUFFER_LEN][RB_DATA_LEN]; + +static int64_t time_diff(struct timespec *t0, struct timespec *t1) +{ + return ((t1->tv_sec * 1000000000) + t1->tv_nsec) - ((t0->tv_sec * 1000000000) + t0->tv_nsec); +} + +/* +static void print_now(char* s) { + fprintf(stdout,s); + fflush(stdout); +} +*/ + +static void report( char* op, int n, uint64_t dt, int redo ) { + fprintf(stdout,"\t%9d %s operations in %4d [ms] => %7d [us] => %10d [ns]\t >>> %6d [ns/op]\t%4d redone operations\n", + n, op, (int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/n), redo ); +} + +struct thread_params { + lf_ring_buffer_t *ring; + int n; + int flags; + uint64_t dt; +}; + +/* +static void feed_data( int n){ + int i; + for(i=0; in, sequential_writes( params->ring, params->n, params->flags ) ); + params->dt = sequential_writes( params->ring, params->n, params->flags ); + return NULL; +} + +void* reader_thread( void* param ) { + struct thread_params *params = (struct thread_params*)param; + //report( "read ", params->n, sequential_reads( params->ring, params->n, params->flags ) ); + params->dt = sequential_reads( params->ring, params->n, params->flags ); + return NULL; +} + +static void parallel_op( int op, int nt, lf_ring_buffer_t *ring, int n, int flags ) { + int i; + uint64_t dt; + + pthread_t *threads = malloc( sizeof(pthread_t)*nt); + struct thread_params *params = malloc( sizeof(struct thread_params)*nt); + + for(i=0; i %7d [us] => %10d [ns]\t >>> %6d [ns/op]\n",(int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/(n/nt)) ); + /* empty the ring */ + free(threads); + free(params); +} + +int main( int argc, char** argv ) { + + int i; + int b_len = BUFFER_LEN; + lf_ring_buffer_t *ring; + + ring = lf_ring_buffer_create( b_len ); + if(ring==NULL){ + fprintf(stderr,"ERROR : lf_ring_buffer_create( %d );\n",b_len); + exit( EXIT_FAILURE ); + } + + /* + print_now("feed the data ... "); + feed_data(b_len); + printf("done.\n"); + */ + + printf("sequential non blocking write operations ...\n"); + sequential_writes( ring, b_len, 0 ); + printf("sequential non blocking read operations ...\n"); + sequential_reads( ring, b_len, 0 ); + if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } + printf("sequential blocking write operations ...\n"); + sequential_writes( ring, b_len, LFRB_NO_BLOCK ); + printf("sequential blocking read operations ...\n"); + sequential_reads( ring, b_len, LFRB_NO_BLOCK ); + if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } + + for(i=5; i<=50;i*=2) { + printf("%d parallel blocking with backoff inc write operations .... \n",i); + parallel_op( 0, i, ring, b_len, 0 ); + printf("parallel blocking read operations ...\n"); + sequential_reads( ring, b_len, 0 ); + if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } + } + for(i=5; i<=50;i*=2) { + printf("%d parallel non blocking write operations .... \n",i); + parallel_op( 0, i, ring, b_len, LFRB_NO_BLOCK ); + printf("non blocking read operations ...\n"); + sequential_reads( ring, b_len, LFRB_NO_BLOCK ); + if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } + } + for(i=10; i<=50;i*=2) { + printf("%d parallel blocking write and read operations .... \n",i*2); + parallel_op( 3, i, ring, b_len, 0 ); + if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); } + } + + lf_ring_buffer_destroy( ring ); + + return EXIT_SUCCESS; +} + -- cgit v1.1-2-g2b99