LCOV - code coverage report
Current view: top level - util/tmpl - fd_stack.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 53 60 88.3 %
Date: 2024-11-13 11:58:15 Functions: 17 20 85.0 %

          Line data    Source code
       1             : /* Declares a family of functions implementing a single-threaded
       2             :    run-time fixed-capacity stack designed for high performance contexts.
       3             :    Example usage:
       4             : 
       5             :      #define STACK_NAME my_stack
       6             :      #define STACK_T    my_ele_t
       7             :      #include "util/tmpl/fd_stack.c"
       8             : 
       9             :    This creates the following API for use in the local compilation unit:
      10             : 
      11             :      ulong      my_stack_align    ( void               ); // required byte alignment of a stack
      12             :      ulong      my_stack_footprint( ulong max          ); // required byte footprint of a stack with max capacity
      13             :      void     * my_stack_new      ( void     * shmem,     // format memory region into a my_stack, my_stack will be empty
      14             :                                     ulong      max );     // (caller not joined on return, mem has required align/footprint, etc)
      15             :      my_ele_t * my_stack_join     ( void     * shstack ); // join a my_stack (unlimited joins, etc) (NOT A CAST OF SHSTACK)
      16             :                                                           // join can be indexed like a normal array with max elements
      17             :                                                           // stack[i] for i in [0,cnt) are the elements currently in the
      18             :                                                           // stack from bottom to top
      19             :      void     * my_stack_leave    ( my_ele_t * stack   ); // leave a my_stack (matched with join, etc) (NOT A CAST OF STACK)
      20             :      void     * my_stack_delete   ( void     * shstack ); // unformat memory (no active joins, etc)
      21             : 
      22             :      // Accessors
      23             : 
      24             :      ulong my_stack_max  ( my_ele_t const * stack ); // returns the max elements that could be in the stack
      25             :      ulong my_stack_cnt  ( my_ele_t const * stack ); // returns the number of elements in the stack, in [0,max]
      26             :      ulong my_stack_avail( my_ele_t const * stack ); // return max-cnt
      27             :      int   my_stack_empty( my_ele_t const * stack ); // returns 1 if empty and 0 otherwise
      28             :      int   my_stack_full ( my_ele_t const * stack ); // returns 1 if full and 0 otherwise
      29             : 
      30             :      // Simple API
      31             : 
      32             :      my_ele_t * my_stack_push( my_ele_t * stack, my_ele_t ele ); // push ele to stack, returns stack
      33             :      my_ele_t   my_stack_pop ( my_ele_t * stack               ); // pop ele from stack, returns ele
      34             : 
      35             :      // Advanced API for zero-copy usage
      36             : 
      37             :      my_ele_t * my_stack_peek      ( my_ele_t * stack ); // peeks at stack top, returned ptr lifetime is until next op on stack
      38             :      my_ele_t * my_stack_insert    ( my_ele_t * stack ); // inserts uninitialized element at tail, returns stack
      39             :      my_ele_t * my_stack_remove    ( my_ele_t * stack ); // removes tail, returns stack
      40             :      my_ele_t * my_stack_remove_all( my_ele_t * stack ); // removes all, returns stack, fast O(1)
      41             : 
      42             :      my_ele_t const * my_stack_peek_const( my_ele_t const * stack ); // const version of peek
      43             : 
      44             :    For performance, none of the functions do any error checking.
      45             :    Specifically, the caller promises that max is such that footprint
      46             :    will not overflow 2^64 (e.g. max << (2^64)/sizeof(my_ele_t)), cnt<max
      47             :    for any push or insert operation and cnt>0 for any pop, peek or
      48             :    remove operation (remove_all is fine on an empty stack). */
      49             : 
      50             : #include "../bits/fd_bits.h"
      51             : #include <stddef.h>
      52             : 
      53             : #ifndef STACK_NAME
      54             : #error "Define STACK_NAME"
      55             : #endif
      56             : 
      57             : #ifndef STACK_T
      58             : #error "Define STACK_T"
      59             : #endif
      60             : 
      61             : /* Implementation *****************************************************/
      62             : 
      63  2766673488 : #define STACK_(x) FD_EXPAND_THEN_CONCAT3(STACK_NAME,_,x)
      64             : 
      65             : struct STACK_(private) {
      66             : 
      67             :   /* The number of elements in the stack is cnt and cnt will be in
      68             :      [0,max].  If cnt==0, the stack is empty.  If cnt==max, the stack if
      69             :      full.  For a non-empty stack, the oldest element in the stack is at
      70             :      element stack[0] and the newest element in the stack is at element
      71             :      stack[cnt-1UL]. */
      72             : 
      73             :   ulong   max;
      74             :   ulong   cnt;
      75             :   STACK_T stack[1]; /* Actually max in size */
      76             : };
      77             : 
      78             : typedef struct STACK_(private) STACK_(private_t);
      79             : 
      80             : FD_PROTOTYPES_BEGIN
      81             : 
      82             : /* private_from_stack return a pointer to the stack_private given a
      83             :    pointer to the stack. */
      84             : 
      85             : FD_FN_CONST static inline STACK_(private_t) *
      86           0 : STACK_(private_hdr_from_stack)( STACK_T * stack ) {
      87           0 :   return (STACK_(private_t) *)( (ulong)stack - offsetof(STACK_(private_t), stack) );
      88           0 : }
      89             : 
      90             : /* const-correct version of above */
      91             : 
      92             : FD_FN_CONST static inline STACK_(private_t) const *
      93           0 : STACK_(private_const_hdr_from_stack)( STACK_T const * stack ) {
      94           0 :   return (STACK_(private_t) const *)( (ulong)stack - offsetof(STACK_(private_t), stack) );
      95           0 : }
      96             : 
      97           0 : FD_FN_CONST static inline ulong STACK_(align)( void ) { return alignof(STACK_(private_t)); }
      98             : 
      99             : FD_FN_CONST static inline ulong
     100           3 : STACK_(footprint)( ulong max ) {
     101           3 :   return fd_ulong_align_up( fd_ulong_align_up( 16UL, alignof(STACK_T) ) + sizeof(STACK_T)*max, alignof(STACK_(private_t)) );
     102           3 : }
     103             : 
     104             : static inline void *
     105             : STACK_(new)( void * shmem,
     106           3 :              ulong  max ) {
     107           3 :   STACK_(private_t) * hdr = (STACK_(private_t) *)shmem;
     108           3 :   hdr->max = max;
     109           3 :   hdr->cnt = 0UL;
     110           3 :   return hdr;
     111           3 : }
     112             : 
     113             : static inline STACK_T *
     114           3 : STACK_(join)( void * shstack ) {
     115           3 :   STACK_(private_t) * hdr = (STACK_(private_t) *)shstack;
     116           3 :   return hdr->stack;
     117           3 : } 
     118             : 
     119           3 : static inline void * STACK_(leave) ( STACK_T * stack   ) { return (void *)STACK_(private_hdr_from_stack)( stack ); }
     120           3 : static inline void * STACK_(delete)( void *    shstack ) { return shstack; }
     121             : 
     122             : FD_FN_PURE static inline ulong
     123   300000003 : STACK_(max)( STACK_T const * stack ) {
     124   300000003 :   return STACK_(private_const_hdr_from_stack)( stack )->max;
     125   300000003 : }
     126             : 
     127             : FD_FN_PURE static inline ulong
     128   300000003 : STACK_(cnt)( STACK_T const * stack ) {
     129   300000003 :   return STACK_(private_const_hdr_from_stack)( stack )->cnt;
     130   300000003 : }
     131             : 
     132             : FD_FN_PURE static inline ulong
     133   300000000 : STACK_(avail)( STACK_T const * stack ) {
     134   300000000 :   STACK_(private_t) const * hdr = STACK_(private_const_hdr_from_stack)( stack );
     135   300000000 :   return hdr->max - hdr->cnt;
     136   300000000 : }
     137             : 
     138             : FD_FN_PURE static inline int
     139   300000000 : STACK_(full)( STACK_T const * stack ) {
     140   300000000 :   STACK_(private_t) const * hdr = STACK_(private_const_hdr_from_stack)( stack );
     141   300000000 :   return hdr->max==hdr->cnt;
     142   300000000 : }
     143             : 
     144             : FD_FN_PURE static inline int
     145   300000000 : STACK_(empty)( STACK_T const * stack ) {
     146   300000000 :   return !STACK_(private_const_hdr_from_stack)( stack )->cnt;
     147   300000000 : }
     148             : 
     149             : static inline STACK_T *
     150             : STACK_(push)( STACK_T * stack,
     151    66667296 :               STACK_T   ele ) {
     152    66667296 :   STACK_(private_t) * hdr = STACK_(private_hdr_from_stack)( stack );
     153    66667296 :   hdr->stack[ hdr->cnt++ ] = ele;
     154    66667296 :   return stack;
     155    66667296 : }
     156             : 
     157             : static inline STACK_T
     158    66682113 : STACK_(pop)( STACK_T * stack ) {
     159    66682113 :   STACK_(private_t) * hdr = STACK_(private_hdr_from_stack)( stack );
     160    66682113 :   return hdr->stack[ --hdr->cnt ];
     161    66682113 : }
     162             : 
     163             : FD_FN_PURE static inline STACK_T *
     164    66678048 : STACK_(peek)( STACK_T * stack ) {
     165    66678048 :   STACK_(private_t) * hdr = STACK_(private_hdr_from_stack)( stack );
     166    66678048 :   return hdr->stack + (hdr->cnt-1UL);
     167    66678048 : }
     168             : 
     169             : FD_FN_PURE static inline STACK_T const *
     170    66645321 : STACK_(peek_const)( STACK_T const * stack ) {
     171    66645321 :   STACK_(private_t) const * hdr = STACK_(private_const_hdr_from_stack)( stack );
     172    66645321 :   return hdr->stack + (hdr->cnt-1UL);
     173    66645321 : }
     174             : 
     175    66678048 : static inline STACK_T * STACK_(insert)    ( STACK_T * stack ) { STACK_(private_hdr_from_stack)( stack )->cnt++;     return stack; }
     176    66645321 : static inline STACK_T * STACK_(remove)    ( STACK_T * stack ) { STACK_(private_hdr_from_stack)( stack )->cnt--;     return stack; }
     177        4548 : static inline STACK_T * STACK_(remove_all)( STACK_T * stack ) { STACK_(private_hdr_from_stack)( stack )->cnt = 0UL; return stack; }
     178             : 
     179             : FD_PROTOTYPES_END
     180             : 
     181             : #undef STACK_
     182             : 
     183             : #undef STACK_T
     184             : #undef STACK_NAME
     185             : 

Generated by: LCOV version 1.14