LCOV - code coverage report
Current view: top level - disco/events - fd_circq.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 1 0.0 %
Date: 2026-02-13 06:06:24 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_events_fd_circq_h
       2             : #define HEADER_fd_src_disco_events_fd_circq_h
       3             : 
       4             : /* The circular buffer is a structure, which stores a queue of messages,
       5             :    supporting two operations: push_back and pop_front.  Unlike a regular
       6             :    queue, the circular buffer is fixed size and push_back must always
       7             :    succeed.
       8             : 
       9             :    To ensure push_back always succeeds, the circular buffer will evict
      10             :    old messages if necessary to make room for the new one.
      11             : 
      12             :    One more complication is that the circular buffer must store
      13             :    metadata about the messages in the data buffer itself, as it does not
      14             :    have a separate metadata region.  The structure of the buffer then
      15             :    looks as follows:
      16             : 
      17             :     +-------+-----+------+-----+-------+-----+------+-----+-------+-----+------+
      18             :     + meta0 | pad | msg0 | pad | meta1 | pad | msg1 | pad | meta2 | pad | msg2 |
      19             :     +-------+-----+------+-----+-------+-----+------+-----+-------+-----+------+
      20             :      ^  |                        ^  |                        ^  |
      21             :      |  +-----next---------next--+  +------------------------+  |
      22             :      |                                                          |
      23             :    head                                                        tail
      24             : 
      25             :    Here, the meta elements are fd_circq_message_t, which each point to
      26             :    the next message in the queue, and head, tail are the head and tail
      27             :    of the queue respectively. */
      28             : 
      29             : #include "../../util/fd_util_base.h"
      30             : 
      31           0 : #define FD_CIRCQ_ALIGN (4096UL)
      32             : 
      33             : struct __attribute__((aligned(FD_CIRCQ_ALIGN))) fd_circq_private {
      34             :   /* Current count of elements in the queue. */
      35             :   ulong cnt;
      36             : 
      37             :   /* These are offsets relative to the end of this struct of the
      38             :      metadata for the first, and last message in the queue,
      39             :      respectively. */
      40             :   ulong head;
      41             :   ulong tail;
      42             : 
      43             :   ulong size;
      44             : 
      45             :   ulong cursor;          /* Current offset in buffer for iteration, or ULONG_MAX if at end */
      46             :   ulong cursor_seq;      /* Monotonic counter - cursor value for current position */
      47             :   ulong cursor_push_seq; /* Monotonic counter - incremented on each push */
      48             : 
      49             :   struct {
      50             :     ulong drop_cnt;
      51             :   } metrics;
      52             : 
      53             :   /* padding out to 4k here ... */
      54             : };
      55             : 
      56             : typedef struct fd_circq_private fd_circq_t;
      57             : 
      58             : FD_PROTOTYPES_BEGIN
      59             : 
      60             : FD_FN_CONST ulong
      61             : fd_circq_align( void );
      62             : 
      63             : FD_FN_CONST ulong
      64             : fd_circq_footprint( ulong sz );
      65             : 
      66             : void *
      67             : fd_circq_new( void * shmem,
      68             :               ulong  sz );
      69             : 
      70             : fd_circq_t *
      71             : fd_circq_join( void * shbuf );
      72             : 
      73             : void *
      74             : fd_circq_leave( fd_circq_t * buf );
      75             : 
      76             : void *
      77             : fd_circq_delete( void * shbuf );
      78             : 
      79             : /* fd_circq_push_back appends a message of size sz into the circular
      80             :    buffer, evicting any old messages if they would be overwritten when
      81             :    the buffer wraps around.  Returns the address of the memory contents
      82             :    in the buffer on success, or NULL on failure.  The only two reasons
      83             :    for failure are if the requested sz (along with the message metadata)
      84             :    exceeds the size of the entire buffer and can't fit, or if the
      85             :    requested alignment is not a power of 2, or is larger than 4096. */
      86             : 
      87             : uchar *
      88             : fd_circq_push_back( fd_circq_t * circq,
      89             :                     ulong        align,
      90             :                     ulong        footprint );
      91             : 
      92             : void
      93             : fd_circq_resize_back( fd_circq_t * circq,
      94             :                       ulong        new_footprint );
      95             : 
      96             : /* fd_circq_cursor_advance moves an internal cursor forward to the next
      97             :    message in the circular buffer, returning the message at the previous
      98             :    cursor position, or NULL if there are no more messages.
      99             : 
     100             :    Moving the cursor does not remove the message from the circular
     101             :    buffer, which only happens when fd_circq_pop_until is called. */
     102             : 
     103             : uchar const *
     104             : fd_circq_cursor_advance( fd_circq_t * circq,
     105             :                          ulong *      msg_sz );
     106             : 
     107             : /* fd_circq_pop_until removes messages from the front of the circular
     108             :    buffer up to and including the message with the given cursor value.
     109             :    Returns 0 on success, or -1 if the given cursor value is invalid
     110             :    (i.e., it is higher than the present cursor of the circq and has
     111             :    never existed.) */
     112             : 
     113             : int
     114             : fd_circq_pop_until( fd_circq_t * circq,
     115             :                     ulong        cursor );
     116             : 
     117             : /* fd_circq_reset_cursor resets the internal cursor to the front of the
     118             :    circular buffer.  This is useful if you want to re-process all
     119             :    messages in the buffer from the start. */
     120             : 
     121             : void
     122             : fd_circq_reset_cursor( fd_circq_t * circq );
     123             : 
     124             : /* fd_circq_bytes_used returns the total number of bytes currently used
     125             :    in the circular buffer, including message metadata and padding. */
     126             : 
     127             : ulong
     128             : fd_circq_bytes_used( fd_circq_t const * circq );
     129             : 
     130             : FD_PROTOTYPES_END
     131             : 
     132             : #endif /* HEADER_fd_src_disco_events_fd_circq_h */

Generated by: LCOV version 1.14