MIDAS
Loading...
Searching...
No Matches
Ring Buffer Functions (rb_xxx)

Classes

struct  RING_BUFFER
 

Macros

#define MAX_RING_BUFFER   100
 

Functions

int rb_set_nonblocking ()
 
int rb_create (int size, int max_event_size, int *handle)
 
int rb_delete (int handle)
 
int rb_get_wp (int handle, void **p, int millisec)
 
int rb_increment_wp (int handle, int size)
 
int rb_get_rp (int handle, void **p, int millisec)
 
int rb_increment_rp (int handle, int size)
 
int rb_get_buffer_level (int handle, int *n_bytes)
 

Variables

static RING_BUFFER rb [MAX_RING_BUFFER]
 
static volatile int _rb_nonblocking = 0
 

Detailed Description

dox dox


Macro Definition Documentation

◆ MAX_RING_BUFFER

#define MAX_RING_BUFFER   100

Definition at line 17302 of file midas.cxx.

Function Documentation

◆ rb_create()

int rb_create ( int  size,
int  max_event_size,
int handle 
)

Create a ring buffer with a given size

Provide an inter-thread buffer scheme for handling front-end events. This code allows concurrent data acquisition, calibration and network transfer on a multi-CPU machine. One thread reads out the data, passes it via the ring buffer functions to another thread running on the other CPU, which can then calibrate and/or send the data over the network.

Parameters
sizeSize of ring buffer, must be larger than 2*max_event_size
max_event_sizeMaximum event size to be placed into
*handleHandle to ring buffer
Returns
DB_SUCCESS, DB_NO_MEMORY, DB_INVALID_PARAM

Definition at line 17358 of file midas.cxx.

17379{
17380 int i;
17381
17382 for (i = 0; i < MAX_RING_BUFFER; i++)
17383 if (rb[i].buffer == NULL)
17384 break;
17385
17386 if (i == MAX_RING_BUFFER)
17387 return DB_NO_MEMORY;
17388
17389 if (size < max_event_size * 2)
17390 return DB_INVALID_PARAM;
17391
17392 memset(&rb[i], 0, sizeof(RING_BUFFER));
17393 rb[i].buffer = (unsigned char *) M_MALLOC(size);
17394 assert(rb[i].buffer);
17395 rb[i].size = size;
17397 rb[i].rp = rb[i].buffer;
17398 rb[i].wp = rb[i].buffer;
17399 rb[i].ep = rb[i].buffer;
17400
17401 *handle = i + 1;
17402
17403 return DB_SUCCESS;
17404}
#define DB_INVALID_PARAM
Definition midas.h:639
#define DB_SUCCESS
Definition midas.h:631
#define DB_NO_MEMORY
Definition midas.h:633
#define MAX_RING_BUFFER
Definition midas.cxx:17302
static RING_BUFFER rb[MAX_RING_BUFFER]
Definition midas.cxx:17304
INT i
Definition mdump.cxx:32
INT max_event_size
Definition mfed.cxx:30
#define M_MALLOC(x)
Definition midas.h:1550
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
unsigned char * wp
Definition midas.cxx:17298
unsigned char * buffer
Definition midas.cxx:17294
unsigned int max_event_size
Definition midas.cxx:17296
unsigned int size
Definition midas.cxx:17295
unsigned char * rp
Definition midas.cxx:17297
unsigned char * ep
Definition midas.cxx:17299
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rb_delete()

int rb_delete ( int  handle)

Delete a ring buffer

Parameters
handleHandle of the ring buffer
Returns
DB_SUCCESS

Definition at line 17412 of file midas.cxx.

17428{
17429 if (handle < 0 || handle >= MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17430 return DB_INVALID_HANDLE;
17431
17432 M_FREE(rb[handle - 1].buffer);
17433 rb[handle - 1].buffer = NULL;
17434 memset(&rb[handle - 1], 0, sizeof(RING_BUFFER));
17435
17436 return DB_SUCCESS;
17437}
#define DB_INVALID_HANDLE
Definition midas.h:635
#define M_FREE(x)
Definition midas.h:1552
Here is the call graph for this function:

◆ rb_get_buffer_level()

int rb_get_buffer_level ( int  handle,
int n_bytes 
)

Return number of bytes in a ring buffer

Parameters
handleHandle of the buffer to get the info
*n_bytesNumber of bytes in buffer
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 17707 of file midas.cxx.

17725{
17726 int h;
17727
17728 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17729 return DB_INVALID_HANDLE;
17730
17731 h = handle - 1;
17732
17733 if (rb[h].wp >= rb[h].rp)
17734 *n_bytes = (POINTER_T) rb[h].wp - (POINTER_T) rb[h].rp;
17735 else
17736 *n_bytes =
17737 (POINTER_T) rb[h].ep - (POINTER_T) rb[h].rp + (POINTER_T) rb[h].wp - (POINTER_T) rb[h].buffer;
17738
17739 return DB_SUCCESS;
17740}
#define POINTER_T
Definition midas.h:166
Here is the call graph for this function:

◆ rb_get_rp()

int rb_get_rp ( int  handle,
void **  p,
int  millisec 
)

Obtain the current read pointer at which new data is available with optional timeout

Parameters
handleRing buffer handle
millisecOptional timeout in milliseconds if buffer is full. Zero to not wait at all (non-blocking)
**pAddress of pointer pointing to newly available data. If p == NULL, only return status.
Returns
DB_SUCCESS, DB_TIEMOUT, DB_INVALID_HANDLE

Definition at line 17590 of file midas.cxx.

17613{
17614 int i, h;
17615
17616 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17617 return DB_INVALID_HANDLE;
17618
17619 h = handle - 1;
17620
17621 for (i = 0; i <= millisec / 10; i++) {
17622
17623 if (rb[h].wp != rb[h].rp) {
17624 if (p != NULL)
17625 *p = rb[handle - 1].rp;
17626 return DB_SUCCESS;
17627 }
17628
17629 if (millisec == 0)
17630 return DB_TIMEOUT;
17631
17632 if (_rb_nonblocking)
17633 return DB_TIMEOUT;
17634
17635 /* wait one time slice */
17636 ss_sleep(10);
17637 }
17638
17639 return DB_TIMEOUT;
17640}
#define DB_TIMEOUT
Definition midas.h:655
INT ss_sleep(INT millisec)
Definition system.cxx:3700
static volatile int _rb_nonblocking
Definition midas.cxx:17306
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rb_get_wp()

int rb_get_wp ( int  handle,
void **  p,
int  millisec 
)

Retrieve write pointer where new data can be written

Parameters
handleRing buffer handle
millisecOptional timeout in milliseconds if buffer is full. Zero to not wait at all (non-blocking)
**pWrite pointer
Returns
DB_SUCCESS, DB_TIMEOUT, DB_INVALID_HANDLE

Definition at line 17449 of file midas.cxx.

17469{
17470 int h, i;
17471 unsigned char *rp;
17472
17473 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17474 return DB_INVALID_HANDLE;
17475
17476 h = handle - 1;
17477
17478 for (i = 0; i <= millisec / 10; i++) {
17479
17480 rp = rb[h].rp; // keep local copy for convenience
17481
17482 /* check if enough size for wp >= rp without wrap-around */
17483 if (rb[h].wp >= rp
17484 && rb[h].wp + rb[h].max_event_size <= rb[h].buffer + rb[h].size - rb[h].max_event_size) {
17485 *p = rb[h].wp;
17486 return DB_SUCCESS;
17487 }
17488
17489 /* check if enough size for wp >= rp with wrap-around */
17490 if (rb[h].wp >= rp && rb[h].wp + rb[h].max_event_size > rb[h].buffer + rb[h].size - rb[h].max_event_size &&
17491 rp > rb[h].buffer) { // next increment of wp wraps around, so need space at beginning
17492 *p = rb[h].wp;
17493 return DB_SUCCESS;
17494 }
17495
17496 /* check if enough size for wp < rp */
17497 if (rb[h].wp < rp && rb[h].wp + rb[h].max_event_size < rp) {
17498 *p = rb[h].wp;
17499 return DB_SUCCESS;
17500 }
17501
17502 if (millisec == 0)
17503 return DB_TIMEOUT;
17504
17505 if (_rb_nonblocking)
17506 return DB_TIMEOUT;
17507
17508 /* wait one time slice */
17509 ss_sleep(10);
17510 }
17511
17512 return DB_TIMEOUT;
17513}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rb_increment_rp()

int rb_increment_rp ( int  handle,
int  size 
)

Increment current read pointer, freeing up space for the writing thread.

Parameters
handleRing buffer handle
sizeNumber of bytes to free up at current read pointer
Returns
DB_SUCCESS, DB_INVALID_PARAM

Definition at line 17652 of file midas.cxx.

17673{
17674 int h;
17675
17676 unsigned char *new_rp;
17677 unsigned char *ep;
17678
17679 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17680 return DB_INVALID_HANDLE;
17681
17682 h = handle - 1;
17683
17684 if ((DWORD) size > rb[h].max_event_size)
17685 return DB_INVALID_PARAM;
17686
17687 new_rp = rb[h].rp + size;
17688 ep = rb[h].ep; // keep local copy of end pointer, rb[h].ep might be changed by other thread
17689
17690 /* wrap around if end pointer reached */
17691 if (new_rp >= ep && rb[h].wp < ep)
17692 new_rp = rb[h].buffer;
17693
17694 rb[handle - 1].rp = new_rp;
17695
17696 return DB_SUCCESS;
17697}
unsigned int DWORD
Definition mcstd.h:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rb_increment_wp()

int rb_increment_wp ( int  handle,
int  size 
)

rb_increment_wp

Increment current write pointer, making the data at the write pointer available to the receiving thread

Parameters
handleRing buffer handle
sizeNumber of bytes placed at the WP
Returns
DB_SUCCESS, DB_INVALID_PARAM, DB_INVALID_HANDLE

Definition at line 17524 of file midas.cxx.

17543{
17544 int h;
17545 unsigned char *new_wp;
17546
17547 if (handle < 1 || handle > MAX_RING_BUFFER || rb[handle - 1].buffer == NULL)
17548 return DB_INVALID_HANDLE;
17549
17550 h = handle - 1;
17551
17552 if ((DWORD) size > rb[h].max_event_size) {
17553 cm_msg(MERROR, "rb_increment_wp", "event size of %d MB larger than max_event_size of %d MB",
17554 size/1024/1024, rb[h].max_event_size/1024/1024);
17555 abort();
17556 }
17557
17558 new_wp = rb[h].wp + size;
17559
17560 /* wrap around wp if not enough space */
17561 if (new_wp > rb[h].buffer + rb[h].size - rb[h].max_event_size) {
17562 rb[h].ep = new_wp;
17563 new_wp = rb[h].buffer;
17564 assert(rb[h].rp != rb[h].buffer);
17565 } else
17566 if (new_wp > rb[h].ep)
17567 rb[h].ep = new_wp;
17568
17569 rb[h].wp = new_wp;
17570
17571 return DB_SUCCESS;
17572}
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:929
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rb_set_nonblocking()

int rb_set_nonblocking ( void  )

dox Set all rb_get_xx to nonblocking. Needed in multi-thread environments for stopping all theads without deadlock

Returns
DB_SUCCESS

Definition at line 17317 of file midas.cxx.

17335{
17336 _rb_nonblocking = 1;
17337
17338 return DB_SUCCESS;
17339}
Here is the caller graph for this function:

Variable Documentation

◆ _rb_nonblocking

volatile int _rb_nonblocking = 0
static

Definition at line 17306 of file midas.cxx.

◆ rb

Definition at line 17304 of file midas.cxx.