LCOV - code coverage report
Current view: top level - util/tmpl - fd_deque_dynamic.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 294 294 100.0 %
Date: 2025-07-01 05:00:49 Functions: 94 62865 0.1 %

          Line data    Source code
       1             : /* Declares a family of functions implementing a single-threaded
       2             :    run-time fixed-capacity double-ended queue (deque) designed for high
       3             :    performance contexts.  Example usage:
       4             : 
       5             :      #define DEQUE_NAME my_deque
       6             :      #define DEQUE_T    my_ele_t
       7             :      #include "util/tmpl/fd_deque.c"
       8             : 
       9             :    This creates the following API for use in the local compilation unit:
      10             : 
      11             :      // Constructors
      12             : 
      13             :      // IMPORTANT SAFETY TIP!  max==0 is fine for this API.  Calling
      14             :      // most APIs on such a deque will be a violation of the API
      15             :      // pre-requisites (e.g. push_head and pop_tail are not valid
      16             :      // because a max==0 deque is simultaneously full and empty).  The
      17             :      // accessors (max==0, cnt==0, avail==0, empty==true, full==true),
      18             :      // remove_all (no-op) and iterators (will indicate nothing to
      19             :      // iterator over) are still valid to use.
      20             : 
      21             :      ulong      my_deque_align    ( void               ); // required byte alignment of a deque
      22             :      ulong      my_deque_footprint( ulong      max     ); // required byte footprint of a deque with max capacity
      23             :      void     * my_deque_new      ( void     * shmem,     // format memory region into a my_deque, my_deque will be empty
      24             :                                     ulong      max     ); // (caller not joined on return, mem has required align/footprint, etc)
      25             :      my_ele_t * my_deque_join     ( void     * shdeque ); // join a my_deque (unlimited joins, etc) (NOT A CAST OF SHDEQUE)
      26             :                                                           // join can be indexed like a normal array with max elements
      27             :      void     * my_deque_leave    ( my_ele_t * deque   ); // leave a my_deque (matched with join, etc) (NOT A CAST OF DEQUE)
      28             :      void     * my_deque_delete   ( void     * shdeque ); // unformat memory (no active joins, etc)
      29             : 
      30             :      // Accessors
      31             : 
      32             :      ulong my_deque_max  ( my_ele_t const * deque ); // returns the max elements that could be in the deque
      33             :      ulong my_deque_cnt  ( my_ele_t const * deque ); // returns the number of elements in the deque, in [0,max]
      34             :      ulong my_deque_avail( my_ele_t const * deque ); // returns max-cnt
      35             :      int   my_deque_empty( my_ele_t const * deque ); // returns 1 if deque is empty and 0 otherwise
      36             :      int   my_deque_full ( my_ele_t const * deque ); // returns 1 if deque is full and 0 otherwise
      37             : 
      38             :      // Simple API
      39             : 
      40             :      // IMPORTANT SAFETY TIP!  The wrap APIs discard the value popped on
      41             :      // wrapping.  Thus, these should not be used when a my_ele_t might
      42             :      // contain the only reference to a resource (memory, file
      43             :      // descriptors, etc) that might need to be released after popping
      44             :      // (e.g. use these only if my_ele_t is plain-old-data).
      45             : 
      46             :      // IMPORTANT SAFETY TIP!  The pop_idx APIs have an O(cnt) worst
      47             :      // case.
      48             : 
      49             :      my_ele_t * my_deque_push_head     ( my_ele_t * deque, my_ele_t ele ); // push ele at the deque head, returns deque
      50             :      my_ele_t * my_deque_push_tail     ( my_ele_t * deque, my_ele_t ele ); // push ele at the deque tail, returns deque
      51             :      my_ele_t   my_deque_pop_head      ( my_ele_t * deque               ); // pops ele from the head of the deque, returns ele
      52             :      my_ele_t   my_deque_pop_tail      ( my_ele_t * deque               ); // pops ele from the tail of the deque, returns ele
      53             :      my_ele_t * my_deque_push_head_wrap( my_ele_t * deque, my_ele_t ele ); // push ele at the deque head (pops tail first if deque full), returns deque, assumes deque has a positive max
      54             :      my_ele_t * my_deque_push_tail_wrap( my_ele_t * deque, my_ele_t ele ); // push ele at the deque tail (pops head first if deque full), returns deque, assumes deque has a positive max
      55             :      my_ele_t   my_deque_pop_idx_tail  ( my_ele_t * deque, ulong    idx ); // pops ele at idx, returns ele. idx in [0,cnt). shifts head <= tail
      56             : 
      57             :      // Advanced API for zero-copy usage
      58             : 
      59             :      my_ele_t * my_deque_peek_head  ( my_ele_t * deque ); // peeks at head, returned ptr lifetime is until next op on deque
      60             :      my_ele_t * my_deque_peek_tail  ( my_ele_t * deque ); // peeks at tail, returned ptr lifetime is until next op on deque
      61             :      my_ele_t * my_deque_peek_index ( my_ele_t * deque, ulong idx ); // peeks at index, returned ptr lifetime is until next op on deque
      62             :      my_ele_t * my_deque_insert_head( my_ele_t * deque ); // inserts uninitialized element at head, returns deque
      63             :      my_ele_t * my_deque_insert_tail( my_ele_t * deque ); // inserts uninitialized element at tail, returns deque
      64             :      my_ele_t * my_deque_remove_head( my_ele_t * deque ); // removes head, returns deque
      65             :      my_ele_t * my_deque_remove_tail( my_ele_t * deque ); // removes tail, returns deque
      66             :      my_ele_t * my_deque_remove_all ( my_ele_t * deque ); // removes all, returns deque, fast O(1)
      67             : 
      68             :      my_ele_t * my_deque_push_head_nocopy( my_ele_t * deque ); // push the head, returns the new uninitialized element
      69             :      my_ele_t * my_deque_push_tail_nocopy( my_ele_t * deque ); // push the tail, returns the new uninitialized element
      70             :      my_ele_t * my_deque_pop_head_nocopy ( my_ele_t * deque ); // pops the head, returns the deleted element
      71             :      my_ele_t * my_deque_pop_tail_nocopy ( my_ele_t * deque ); // pops the tail, returns the deleted element
      72             : 
      73             :      my_ele_t const * my_deque_peek_head_const( my_ele_t const * deque ); // const version of peek_head
      74             :      my_ele_t const * my_deque_peek_tail_const( my_ele_t const * deque ); // const version of peek_tail
      75             :      my_ele_t const * my_deque_peek_index_const( my_ele_t const * deque, ulong idx ); // const version of peek_index
      76             : 
      77             :      // my_deque_iter_* allow for iteration over all the elements in
      78             :      // a my_deque.  The iteration will be in order from head to tail.
      79             :      // Example usage:
      80             :      //
      81             :      //   for( my_deque_iter_t iter = my_deque_iter_init( deque ); !my_deque_iter_done( deque, iter ); iter = my_deque_iter_next( deque, iter ) ) {
      82             :      //     my_deque_t * ele = my_deque_iter_ele( deque, iter );
      83             :      //
      84             :      //     ... process ele here
      85             :      //   }
      86             : 
      87             :      my_deque_iter_t  my_deque_iter_init     ( my_deque_t const * deque );
      88             :      int              my_deque_iter_done     ( my_deque_t const * deque, my_deque_iter_t iter ); // returns 1 if no more iterations, 0 o.w.
      89             :      my_deque_iter_t  my_deque_iter_next     ( my_deque_t const * deque, my_deque_iter_t iter ); // returns next iter value iter
      90             :      my_ele_t *       my_deque_iter_ele      ( my_deque_t *       deque, my_deque_iter_t iter ); // assumes not done, return non-NULL ele
      91             :      my_ele_t const * my_deque_iter_ele_const( my_deque_t const * deque, my_deque_iter_t iter ); // assumes not done, return non-NULL ele
      92             : 
      93             :      // my_deque_iter_rev_* allow for iteration similar to the above, but
      94             :      // in reverse order from tail to head.
      95             :      // Example usage:
      96             :      //
      97             :      //   for( my_deque_iter_t iter = my_deque_iter_init_rev( deque ); !my_deque_iter_done_rev( deque, iter ); iter = my_deque_iter_prev( deque, iter ) ) {
      98             :      //     my_deque_t * ele = my_deque_iter_ele( deque, iter );
      99             :      //
     100             :      //     ... process ele here
     101             :      //   }
     102             : 
     103             :      my_deque_iter_t  my_deque_iter_init_rev ( my_deque_t const * deque );
     104             :      int              my_deque_iter_done_rev ( my_deque_t const * deque, my_deque_iter_t iter ); // returns 1 if no more iterations, 0 o.w.
     105             :      my_deque_iter_t  my_deque_iter_prev     ( my_deque_t const * deque, my_deque_iter_t iter ); // returns prev iter value iter
     106             : 
     107             :    For performance, none of the functions do any error checking.
     108             :    Specifically, the caller promises that max is such that footprint
     109             :    will not overflow 2^64 (e.g. max << (2^64)/sizeof(my_ele_t)), cnt<max
     110             :    for any push or insert operation and cnt>0 for any pop, peek or
     111             :    remove operation (remove_all is fine on an empty deque). */
     112             : 
     113             : #include "../bits/fd_bits.h"
     114             : #include <stddef.h>
     115             : 
     116             : #ifndef DEQUE_NAME
     117             : #error "Define DEQUE_NAME"
     118             : #endif
     119             : 
     120             : #ifndef DEQUE_T
     121             : #error "Define DEQUE_T"
     122             : #endif
     123             : 
     124             : #if FD_TMPL_USE_HANDHOLDING
     125             : #include "../log/fd_log.h"
     126             : #endif
     127             : 
     128             : /* Implementation *****************************************************/
     129             : 
     130  5654395602 : #define DEQUE_(x) FD_EXPAND_THEN_CONCAT3(DEQUE_NAME,_,x)
     131             : 
     132             : struct DEQUE_(private) {
     133             :   ulong   max1;  /* Max elements in deque minus 1 */
     134             :   ulong   cnt;   /* Num elements in deque, in [0,max] */
     135             :   ulong   start; /* Location of current head, in [0,max) */
     136             :   ulong   end;   /* Location of current tail, in [0,max) */
     137             :   DEQUE_T deque[ 1 ]; /* Actually max in size */
     138             : };
     139             : 
     140             : typedef struct DEQUE_(private) DEQUE_(private_t);
     141             : 
     142             : FD_PROTOTYPES_BEGIN
     143             : 
     144             : /* private_from_deque returns a pointer to the deque_private given a
     145             :    pointer to the deque. */
     146             : 
     147             : FD_FN_CONST static inline DEQUE_(private_t) *
     148   610986366 : DEQUE_(private_hdr_from_deque)( DEQUE_T * deque ) {
     149   610986366 :   return (DEQUE_(private_t) *)( (ulong)deque - offsetof(DEQUE_(private_t), deque) );
     150   610986366 : }
     151             : 
     152             : /* const-correct version of above */
     153             : 
     154             : FD_FN_CONST static inline DEQUE_(private_t) const *
     155  2084171997 : DEQUE_(private_const_hdr_from_deque)( DEQUE_T const * deque ) {
     156  2084171997 :   return (DEQUE_(private_t) const *)( (ulong)deque - offsetof(DEQUE_(private_t), deque) );
     157  2084171997 : }
     158             : 
     159             : /* These move i to the previous or next slot to i for given max.
     160             :    Input should be in [0,max) and output will be in [0,max). */
     161             : 
     162   279630990 : FD_FN_CONST static inline ulong DEQUE_(private_prev)( ulong i, ulong max1 ) { return fd_ulong_if( i==0UL,  max1, i-1UL ); }
     163   249130386 : FD_FN_CONST static inline ulong DEQUE_(private_next)( ulong i, ulong max1 ) { return fd_ulong_if( i>=max1, 0UL,  i+1UL ); }
     164             : 
     165        3276 : FD_FN_CONST static inline ulong DEQUE_(align)( void ) { return alignof(DEQUE_(private_t)); }
     166             : 
     167             : FD_FN_CONST static inline ulong
     168        1665 : DEQUE_(footprint)( ulong max ) {
     169        1665 :   return fd_ulong_align_up( fd_ulong_align_up( 32UL, alignof(DEQUE_T) ) + sizeof(DEQUE_T)*max, alignof(DEQUE_(private_t)) );
     170        1665 : }
     171             : 
     172             : static inline void *
     173             : DEQUE_(new)( void * shmem,
     174         660 :              ulong  max ) {
     175             : # if FD_TMPL_USE_HANDHOLDING
     176             :   if( FD_UNLIKELY( !shmem                                                ) ) FD_LOG_CRIT(( "NULL shmem" ));
     177             :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, DEQUE_(align)() ) ) ) FD_LOG_CRIT(( "unaligned shmem" ));
     178             : # endif
     179         660 :   DEQUE_(private_t) * hdr = (DEQUE_(private_t) *)shmem;
     180         660 :   hdr->max1  = max-1UL; /* Note: will wrap to ULONG_MAX if max==0 (and ULONG_MAX+1 will wrap back to 0) */
     181         660 :   hdr->cnt   = 0UL;
     182         660 :   hdr->start = 0UL;
     183         660 :   hdr->end   = 0UL;
     184         660 :   return hdr;
     185         660 : }
     186             : 
     187             : static inline DEQUE_T *
     188        1290 : DEQUE_(join)( void * shdeque ) {
     189        1290 :   DEQUE_(private_t) * hdr = (DEQUE_(private_t) *)shdeque;
     190        1290 :   return hdr->deque;
     191        1290 : }
     192             : 
     193         978 : static inline void * DEQUE_(leave) ( DEQUE_T * deque   ) { return (void *)DEQUE_(private_hdr_from_deque)( deque ); }
     194             : 
     195             : static inline void *
     196         348 : DEQUE_(delete)( void * shdeque ) {
     197             : # if FD_TMPL_USE_HANDHOLDING
     198             :   if( FD_UNLIKELY( !shdeque                                                ) ) FD_LOG_CRIT(( "NULL shdeque" ));
     199             :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shdeque, DEQUE_(align)() ) ) ) FD_LOG_CRIT(( "unaligned shmem" ));
     200             : # endif
     201         348 :   return shdeque;
     202         348 : }
     203             : 
     204             : FD_FN_PURE static inline ulong
     205   300000006 : DEQUE_(max)( DEQUE_T const * deque ) {
     206   300000006 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     207   300000006 :   return hdr->max1 + 1UL;
     208   300000006 : }
     209             : 
     210             : FD_FN_PURE static inline ulong
     211   300000333 : DEQUE_(cnt)( DEQUE_T const * deque ) {
     212   300000333 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     213   300000333 :   return hdr->cnt;
     214   300000333 : }
     215             : 
     216             : FD_FN_PURE static inline ulong
     217   300000003 : DEQUE_(avail)( DEQUE_T const * deque ) {
     218   300000003 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     219   300000003 :   return hdr->max1 + 1UL - hdr->cnt;
     220   300000003 : }
     221             : 
     222             : FD_FN_PURE static inline int
     223   300000003 : DEQUE_(empty)( DEQUE_T const * deque ) {
     224   300000003 :   return !DEQUE_(private_const_hdr_from_deque)( deque )->cnt;
     225   300000003 : }
     226             : 
     227             : FD_FN_PURE static inline int
     228   300000003 : DEQUE_(full)( DEQUE_T const * deque ) {
     229   300000003 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     230   300000003 :   return (hdr->max1 + 1UL)==hdr->cnt;
     231   300000003 : }
     232             : 
     233             : static inline DEQUE_T *
     234             : DEQUE_(push_head)( DEQUE_T * deque,
     235    14490972 :                    DEQUE_T   ele ) {
     236             : # if FD_TMPL_USE_HANDHOLDING
     237             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot push to full deque" ));
     238             : # endif
     239    14490972 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     240    14490972 :   ulong max1  = hdr->max1;
     241    14490972 :   ulong cnt   = hdr->cnt;
     242    14490972 :   ulong start = hdr->start;
     243    14490972 :   start = DEQUE_(private_prev)( start, max1 );
     244    14490972 :   hdr->deque[ start ] = ele;
     245    14490972 :   hdr->cnt   = cnt+1UL;
     246    14490972 :   hdr->start = start;
     247    14490972 :   return deque;
     248    14490972 : }
     249             : 
     250             : static inline DEQUE_T *
     251             : DEQUE_(push_tail)( DEQUE_T * deque,
     252    14507661 :                    DEQUE_T   ele ) {
     253             : # if FD_TMPL_USE_HANDHOLDING
     254             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot push to full deque" ));
     255             : # endif
     256    14507661 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     257    14507661 :   ulong max1 = hdr->max1;
     258    14507661 :   ulong cnt  = hdr->cnt;
     259    14507661 :   ulong end  = hdr->end;
     260    14507661 :   hdr->deque[ end ] = ele;
     261    14507661 :   end = DEQUE_(private_next)( end, max1 );
     262    14507661 :   hdr->cnt = cnt+1UL;
     263    14507661 :   hdr->end = end;
     264    14507661 :   return deque;
     265    14507661 : }
     266             : 
     267             : static inline DEQUE_T
     268    16554267 : DEQUE_(pop_head)( DEQUE_T * deque ) {
     269    16554267 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     270             : # if FD_TMPL_USE_HANDHOLDING
     271             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot pop from empty deque" ));
     272             : # endif
     273    16554267 :   ulong max1  = hdr->max1;
     274    16554267 :   ulong cnt   = hdr->cnt;
     275    16554267 :   ulong start = hdr->start;
     276    16554267 :   DEQUE_T ele = hdr->deque[ start ];
     277    16554267 :   start = DEQUE_(private_next)( start, max1 );
     278    16554267 :   hdr->cnt   = cnt-1UL;
     279    16554267 :   hdr->start = start;
     280    16554267 :   return ele;
     281    16554267 : }
     282             : 
     283             : static inline DEQUE_T
     284    16565439 : DEQUE_(pop_tail)( DEQUE_T * deque ) {
     285             : # if FD_TMPL_USE_HANDHOLDING
     286             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot pop from empty deque" ));
     287             : # endif
     288    16565439 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     289    16565439 :   ulong max1 = hdr->max1;
     290    16565439 :   ulong cnt  = hdr->cnt;
     291    16565439 :   ulong end  = hdr->end;
     292    16565439 :   end = DEQUE_(private_prev)( end, max1 );
     293    16565439 :   DEQUE_T ele = hdr->deque[ end ];
     294    16565439 :   hdr->cnt = cnt-1UL;
     295    16565439 :   hdr->end = end;
     296    16565439 :   return ele;
     297    16565439 : }
     298             : 
     299             : static inline DEQUE_T *
     300             : DEQUE_(push_head_wrap)( DEQUE_T * deque,
     301    17635728 :                         DEQUE_T   ele ) {
     302    17635728 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     303    17635728 :   ulong max1  = hdr->max1;
     304    17635728 :   ulong cnt   = hdr->cnt;
     305    17635728 :   ulong start = hdr->start;
     306    17635728 :   ulong end   = hdr->end;
     307             : 
     308             : # if FD_TMPL_USE_HANDHOLDING
     309             :   if( FD_UNLIKELY( max1==ULONG_MAX ) ) FD_LOG_CRIT(( "cannot push_head_wrap when max is zero" ));
     310             : # endif
     311             : 
     312             :   /* If the deque is full, pop and discard the tail. */
     313             : 
     314    17635728 :   int is_full = (cnt>max1);
     315    17635728 :   end  = fd_ulong_if( !is_full, end, DEQUE_(private_prev)( end, max1 ) );
     316    17635728 :   cnt -= (ulong)is_full;
     317             : 
     318             :   /* Push the head */
     319             : 
     320    17635728 :   start = DEQUE_(private_prev)( start, max1 );
     321    17635728 :   hdr->deque[ start ] = ele;
     322             : 
     323    17635728 :   hdr->cnt   = cnt + 1UL;
     324    17635728 :   hdr->start = start;
     325    17635728 :   hdr->end   = end;
     326    17635728 :   return deque;
     327    17635728 : }
     328             : 
     329             : static inline DEQUE_T *
     330             : DEQUE_(push_tail_wrap)( DEQUE_T * deque,
     331    17650173 :                         DEQUE_T   ele ) {
     332    17650173 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     333    17650173 :   ulong max1  = hdr->max1;
     334    17650173 :   ulong cnt   = hdr->cnt;
     335    17650173 :   ulong start = hdr->start;
     336    17650173 :   ulong end   = hdr->end;
     337             : 
     338             : # if FD_TMPL_USE_HANDHOLDING
     339             :   if( FD_UNLIKELY( max1==ULONG_MAX ) ) FD_LOG_CRIT(( "cannot push_tail_wrap when max is zero" ));
     340             : # endif
     341             : 
     342             :   /* If the deque is full, pop and discard the head. */
     343             : 
     344    17650173 :   int is_full = (cnt>max1);
     345    17650173 :   start  = fd_ulong_if( !is_full, start, DEQUE_(private_next)( start, max1 ) );
     346    17650173 :   cnt   -= (ulong)is_full;
     347             : 
     348             :   /* Push the head */
     349             : 
     350    17650173 :   hdr->deque[ end ] = ele;
     351    17650173 :   end = DEQUE_(private_next)( end, max1 );
     352             : 
     353    17650173 :   hdr->cnt   = cnt + 1UL;
     354    17650173 :   hdr->start = start;
     355    17650173 :   hdr->end   = end;
     356    17650173 :   return deque;
     357    17650173 : }
     358             : 
     359             : static inline DEQUE_T
     360    16566648 : DEQUE_(pop_idx_tail)( DEQUE_T * deque, ulong idx ) {
     361             : # if FD_TMPL_USE_HANDHOLDING
     362             :   if( FD_UNLIKELY( DEQUE_(empty)( deque )    ) ) FD_LOG_CRIT(( "cannot pop from empty deque" ));
     363             :   if( FD_UNLIKELY( idx>=DEQUE_(cnt)( deque ) ) ) FD_LOG_CRIT(( "index out of bounds" ));
     364             : # endif
     365    16566648 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     366             : 
     367    16566648 :   ulong max1 = hdr->max1;
     368             : 
     369    16566648 :   ulong slot = hdr->start + idx;
     370    16566648 :         slot = fd_ulong_if( slot <= max1, slot, slot - max1 - 1UL );
     371    16566648 :   ulong cnt  = --hdr->cnt;
     372    16566648 :   ulong rem  = cnt - idx;
     373             : 
     374    16566648 :   hdr->end   = DEQUE_(private_prev)( hdr->end, max1 );
     375             : 
     376    16566648 :   DEQUE_T * cur = &deque[ slot ];
     377    16566648 :   DEQUE_T   ele = *cur;
     378    51241827 :   while( rem-- ) {
     379    34675179 :     slot = DEQUE_(private_next)( slot, max1 );
     380    34675179 :     DEQUE_T * next = &deque[ slot ];
     381    34675179 :     *cur = *next;
     382    34675179 :      cur =  next;
     383    34675179 :   }
     384    16566648 :   return ele;
     385    16566648 : }
     386             : 
     387             : FD_FN_PURE static inline DEQUE_T *
     388    14489388 : DEQUE_(peek_head)( DEQUE_T * deque ) {
     389             : # if FD_TMPL_USE_HANDHOLDING
     390             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     391             : # endif
     392    14489388 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     393    14489388 :   return hdr->deque + hdr->start;
     394    14489388 : }
     395             : 
     396             : FD_FN_PURE static inline DEQUE_T *
     397    14492730 : DEQUE_(peek_tail)( DEQUE_T * deque ) {
     398             : # if FD_TMPL_USE_HANDHOLDING
     399             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     400             : # endif
     401    14492730 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     402    14492730 :   return hdr->deque + DEQUE_(private_prev)( hdr->end, hdr->max1 );
     403    14492730 : }
     404             : 
     405             : FD_FN_PURE static inline DEQUE_T *
     406   171909807 : DEQUE_(peek_index)( DEQUE_T * deque, ulong idx ) {
     407             : # if FD_TMPL_USE_HANDHOLDING
     408             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     409             : # endif
     410   171909807 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     411   171909807 :   ulong slot = hdr->start + idx;
     412   171909807 :         slot = fd_ulong_if( slot <= hdr->max1, slot, slot - hdr->max1 - 1UL );
     413   171909807 :   return hdr->deque + slot;
     414   171909807 : }
     415             : 
     416             : FD_FN_PURE static inline DEQUE_T const *
     417    16557435 : DEQUE_(peek_head_const)( DEQUE_T const * deque ) {
     418             : # if FD_TMPL_USE_HANDHOLDING
     419             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     420             : # endif
     421    16557435 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     422    16557435 :   return hdr->deque + hdr->start;
     423    16557435 : }
     424             : 
     425             : FD_FN_PURE static inline DEQUE_T const *
     426    16567389 : DEQUE_(peek_tail_const)( DEQUE_T const * deque ) {
     427             : # if FD_TMPL_USE_HANDHOLDING
     428             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     429             : # endif
     430    16567389 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     431    16567389 :   return hdr->deque + DEQUE_(private_prev)( hdr->end, hdr->max1 );
     432    16567389 : }
     433             : 
     434             : FD_FN_PURE static inline DEQUE_T const *
     435   343819614 : DEQUE_(peek_index_const)( DEQUE_T const * deque, ulong idx ) {
     436             : # if FD_TMPL_USE_HANDHOLDING
     437             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot peek on empty deque" ));
     438             : # endif
     439   343819614 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     440   343819614 :   ulong slot = hdr->start + idx;
     441   343819614 :         slot = fd_ulong_if( slot <= hdr->max1, slot, slot - hdr->max1 - 1UL );
     442   343819614 :   return hdr->deque + slot;
     443   343819614 : }
     444             : 
     445             : static inline DEQUE_T *
     446    14489388 : DEQUE_(insert_head)( DEQUE_T * deque ) {
     447             : # if FD_TMPL_USE_HANDHOLDING
     448             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot insert into full deque" ));
     449             : # endif
     450    14489388 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     451    14489388 :   ulong max1  = hdr->max1;
     452    14489388 :   ulong cnt   = hdr->cnt;
     453    14489388 :   ulong start = hdr->start;
     454    14489388 :   hdr->cnt    = cnt + 1UL;
     455    14489388 :   hdr->start  = DEQUE_(private_prev)( start, max1 );
     456    14489388 :   return deque;
     457    14489388 : }
     458             : 
     459             : static inline DEQUE_T *
     460    14492730 : DEQUE_(insert_tail)( DEQUE_T * deque ) {
     461             : # if FD_TMPL_USE_HANDHOLDING
     462             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot insert into full deque" ));
     463             : # endif
     464    14492730 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     465    14492730 :   ulong max1 = hdr->max1;
     466    14492730 :   ulong cnt  = hdr->cnt;
     467    14492730 :   ulong end  = hdr->end;
     468    14492730 :   hdr->cnt   = cnt + 1UL;
     469    14492730 :   hdr->end   = DEQUE_(private_next)( end, max1 );
     470    14492730 :   return deque;
     471    14492730 : }
     472             : 
     473             : static inline DEQUE_T *
     474    16557435 : DEQUE_(remove_head)( DEQUE_T * deque ) {
     475             : # if FD_TMPL_USE_HANDHOLDING
     476             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot remove from empty deque" ));
     477             : # endif
     478    16557435 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     479    16557435 :   ulong max1  = hdr->max1;
     480    16557435 :   ulong cnt   = hdr->cnt;
     481    16557435 :   ulong start = hdr->start;
     482    16557435 :   hdr->cnt    = cnt - 1UL;
     483    16557435 :   hdr->start  = DEQUE_(private_next)( start, max1 );
     484    16557435 :   return deque;
     485    16557435 : }
     486             : 
     487             : static inline DEQUE_T *
     488    16567389 : DEQUE_(remove_tail)( DEQUE_T * deque ) {
     489             : # if FD_TMPL_USE_HANDHOLDING
     490             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot remove from empty deque" ));
     491             : # endif
     492    16567389 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     493    16567389 :   ulong max1 = hdr->max1;
     494    16567389 :   ulong cnt  = hdr->cnt;
     495    16567389 :   ulong end  = hdr->end;
     496    16567389 :   hdr->cnt   = cnt - 1UL;
     497    16567389 :   hdr->end   = DEQUE_(private_prev)( end, max1 );
     498    16567389 :   return deque;
     499    16567389 : }
     500             : 
     501             : static inline DEQUE_T *
     502    14484999 : DEQUE_(push_head_nocopy)( DEQUE_T * deque ) {
     503             : # if FD_TMPL_USE_HANDHOLDING
     504             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot push to full deque" ));
     505             : # endif
     506    14484999 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     507    14484999 :   ulong max1  = hdr->max1;
     508    14484999 :   ulong cnt   = hdr->cnt;
     509    14484999 :   ulong start = hdr->start;
     510    14484999 :   hdr->cnt    = cnt + 1UL;
     511    14484999 :   hdr->start  = DEQUE_(private_prev)( start, max1 );
     512    14484999 :   return hdr->deque + hdr->start;
     513    14484999 : }
     514             : 
     515             : static inline DEQUE_T *
     516    14500977 : DEQUE_(push_tail_nocopy)( DEQUE_T * deque ) {
     517             : # if FD_TMPL_USE_HANDHOLDING
     518             :   if( FD_UNLIKELY( DEQUE_(full)( deque ) ) ) FD_LOG_CRIT(( "cannot push to full deque" ));
     519             : # endif
     520    14500977 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     521    14500977 :   ulong max1 = hdr->max1;
     522    14500977 :   ulong cnt  = hdr->cnt;
     523    14500977 :   ulong end  = hdr->end;
     524    14500977 :   hdr->cnt   = cnt + 1UL;
     525    14500977 :   DEQUE_T * res = hdr->deque + hdr->end;
     526    14500977 :   hdr->end   = DEQUE_(private_next)( end, max1 );
     527    14500977 :   return res;
     528    14500977 : }
     529             : 
     530             : static inline DEQUE_T *
     531    16557555 : DEQUE_(pop_head_nocopy)( DEQUE_T * deque ) {
     532             : # if FD_TMPL_USE_HANDHOLDING
     533             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot pop from empty deque" ));
     534             : # endif
     535    16557555 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     536    16557555 :   ulong max1  = hdr->max1;
     537    16557555 :   ulong cnt   = hdr->cnt;
     538    16557555 :   ulong start = hdr->start;
     539    16557555 :   hdr->cnt    = cnt - 1UL;
     540    16557555 :   DEQUE_T * res = hdr->deque + hdr->start;
     541    16557555 :   hdr->start  = DEQUE_(private_next)( start, max1 );
     542    16557555 :   return res;
     543    16557555 : }
     544             : 
     545             : static inline DEQUE_T *
     546    16557516 : DEQUE_(pop_tail_nocopy)( DEQUE_T * deque ) {
     547             : # if FD_TMPL_USE_HANDHOLDING
     548             :   if( FD_UNLIKELY( DEQUE_(empty)( deque ) ) ) FD_LOG_CRIT(( "cannot pop from empty deque" ));
     549             : # endif
     550    16557516 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     551    16557516 :   ulong max1 = hdr->max1;
     552    16557516 :   ulong cnt  = hdr->cnt;
     553    16557516 :   ulong end  = hdr->end;
     554    16557516 :   hdr->cnt   = cnt - 1UL;
     555    16557516 :   hdr->end   = DEQUE_(private_prev)( end, max1 );
     556    16557516 :   return hdr->deque + hdr->end;
     557    16557516 : }
     558             : 
     559             : static inline DEQUE_T *
     560        4488 : DEQUE_(remove_all)( DEQUE_T * deque ) {
     561        4488 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     562        4488 :   hdr->cnt   = 0UL;
     563        4488 :   hdr->start = 0UL;
     564        4488 :   hdr->end   = 0UL;
     565        4488 :   return deque;
     566        4488 : }
     567             : 
     568             : typedef struct { ulong rem; ulong idx; } DEQUE_(iter_t);
     569             : 
     570             : static inline DEQUE_(iter_t)
     571    17665620 : DEQUE_(iter_init)( DEQUE_T const * deque ) {
     572    17665620 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     573    17665620 :   DEQUE_(iter_t) iter;
     574    17665620 :   iter.rem = hdr->cnt;
     575    17665620 :   iter.idx = hdr->start;
     576    17665620 :   return iter;
     577    17665620 : }
     578             : 
     579             : static inline DEQUE_(iter_t)
     580    17650911 : DEQUE_(iter_init_rev)( DEQUE_T const * deque ) {
     581    17650911 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     582    17650911 :   DEQUE_(iter_t) iter;
     583    17650911 :   iter.rem = hdr->cnt;
     584    17650911 :   iter.idx = hdr->end;
     585    17650911 :   iter.idx = DEQUE_(private_prev)( iter.idx, hdr->max1 );
     586    17650911 :   return iter;
     587    17650911 : }
     588             : 
     589             : static inline int
     590   103649856 : DEQUE_(iter_done)( DEQUE_T const * deque, DEQUE_(iter_t) iter ) {
     591   103649856 :   (void)deque;
     592   103649856 :   return !iter.rem;
     593   103649856 : }
     594             : 
     595             : static inline int
     596   103577064 : DEQUE_(iter_done_rev)( DEQUE_T const * deque, DEQUE_(iter_t) iter ) {
     597   103577064 :   (void)deque;
     598   103577064 :   return !iter.rem;
     599   103577064 : }
     600             : 
     601             : static inline DEQUE_(iter_t)
     602    85984236 : DEQUE_(iter_next)( DEQUE_T const * deque, DEQUE_(iter_t) iter ) {
     603    85984236 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     604    85984236 :   iter.rem--;
     605    85984236 :   iter.idx = DEQUE_(private_next)( iter.idx, hdr->max1 );
     606    85984236 :   return iter;
     607    85984236 : }
     608             : 
     609             : static inline DEQUE_(iter_t)
     610    85926153 : DEQUE_(iter_prev)( DEQUE_T const * deque, DEQUE_(iter_t) iter ) {
     611    85926153 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     612    85926153 :   iter.rem--;
     613    85926153 :   iter.idx = DEQUE_(private_prev)( iter.idx, hdr->max1 );
     614    85926153 :   return iter;
     615    85926153 : }
     616             : 
     617             : static inline DEQUE_T *
     618   171910098 : DEQUE_(iter_ele)( DEQUE_T * deque, DEQUE_(iter_t) iter ) {
     619   171910098 :   DEQUE_(private_t) * hdr = DEQUE_(private_hdr_from_deque)( deque );
     620             : # if FD_TMPL_USE_HANDHOLDING
     621             :   if( FD_UNLIKELY( (iter.rem==0) | (iter.rem>hdr->cnt) ) ) FD_LOG_CRIT(( "iter out of bounds" ));
     622             : # endif
     623   171910098 :   return hdr->deque + iter.idx;
     624   171910098 : }
     625             : 
     626             : static inline DEQUE_T const *
     627         291 : DEQUE_(iter_ele_const)( DEQUE_T const * deque, DEQUE_(iter_t) iter ) {
     628         291 :   DEQUE_(private_t) const * hdr = DEQUE_(private_const_hdr_from_deque)( deque );
     629             : # if FD_TMPL_USE_HANDHOLDING
     630             :   if( FD_UNLIKELY( (iter.rem==0) | (iter.rem>hdr->cnt) ) ) FD_LOG_CRIT(( "iter out of bounds" ));
     631             : # endif
     632         291 :   return hdr->deque + iter.idx;
     633         291 : }
     634             : 
     635             : FD_PROTOTYPES_END
     636             : 
     637             : #undef DEQUE_
     638             : 
     639             : #undef DEQUE_T
     640             : #undef DEQUE_NAME

Generated by: LCOV version 1.14