/* * Copyright (c) 2020 Elvees (support@elvees.com) * $Id: $ * $Name: Dmitry Evtushenko $ */ #ifndef __fifo_h #define __fifo_h //#include "fifo.h" #ifdef __linux__ #include "linux/types.h" //#include #elif defined(__FREERTOS__) #include "types.h" //#include "platform.h" #endif //__FREERTOS__ #define USE_FIFO_DEBUG typedef void *(*pf_create_fitem_t)(void *); typedef void (*pf_delete_fitem_t)(void *); enum e_fifo_opt { FIFO_OPT__NONE =0, FIFO_OPT__DOUBLE_LINK =1 }; // Fifo item with single link (next only): struct fitem_s { struct fitem_s *p_next; //struct SRItem *pPrev; }; typedef struct fitem_s fitem_t; // Fifo item with double link (next and previous): struct dfitem_s { struct dfitem_s *p_next; struct dfitem_s *p_prev; }; typedef struct dfitem_s dfitem_t; // Fifo of items (as ring) with single links (only to next items): // Initial conditions: pFirstFree == pFirstLaid == pBegin. // pFirstFree is moving from pFirstLaid and to pFirstLaid but doesn't touch in. // pFirstLaid is trying to catch up pFirstFree and complete with it. // Can be used for inter-threading communication (without mutex, semaphore and so on). // (Efficacy (filling) of FIFO buffer is equal to szFifo-1.) struct fifo_s { struct fitem_s *p_begin; //- begin item in FIFO ring u32 sz_fifo; //- FIFO size (in items) pf_create_fitem_t pf_create; // - hook for item creation pf_delete_fitem_t pf_delete; // - hook for item clearing void *p_crt_arg; // - pointer to argument of pf_create struct fitem_s *p_first_free; //- pointer to first free item struct fitem_s *p_first_held; //- pointer to first held item or // pointer to pFirstFree if FIFO is empty //int cntItems; //- count of filling items u32 opt; #ifdef USE_FIFO_DEBUG u32 cntFree; //- free operation counter u32 cntHeld; //- held operation counter #endif //-USE_FIFO_DEBUG } ; typedef struct fifo_s fifo_t; #ifdef __cplusplus extern "C" { #endif extern bool fifo_init( struct fifo_s *pf, u32 sz_fifo, u32 sz_item, pf_create_fitem_t pf_create, void *pcarg, pf_delete_fitem_t pf_delete, u32 opt); extern void fifo_free( struct fifo_s *pf); //extern void fifo_reset( struct fifo_s *pf); extern void fifo_reset( struct fifo_s *pf); //functional of first thread (held): //extern struct fitem_s *fifo_get_first_free( struct fifo_s *pf); static inline struct fitem_s *fifo_get_first_free( struct fifo_s *pf) { return ((pf->p_first_free->p_next != pf->p_first_held) ? pf->p_first_free : NULL); } extern struct fitem_s *fifo_hold_first_free( struct fifo_s *pf); extern int fifo_get_free_cnt( struct fifo_s *pf); extern bool fifo_is_next_free( struct fifo_s *pf, int cntFree); //functional of second thread (taken): //extern struct fitem_s *fifo_get_first_held( struct fifo_s *pf); static inline struct fitem_s *fifo_get_first_held( struct fifo_s *pf) { return ((pf->p_first_held != pf->p_first_free) ? pf->p_first_held : NULL); } extern struct fitem_s *fifo_free_first_held( struct fifo_s *pf); extern int fifo_get_held_cnt( struct fifo_s *pf); extern bool fifo_is_next_held( struct fifo_s *pf, int cntLaid); extern void fifo_print( struct fifo_s *pf); #ifdef USE_FIFO_DEBUG //extern void fifo_reset_counters( struct fifo_s *pf); //extern u32 fifo_get_held_qnt( struct fifo_s *pf); static inline void fifo_reset_counters( struct fifo_s *pf) { pf->cntFree = pf->cntHeld = 0; } // get current quantity of held item as difference between counters: // inaccurate estimate in multithreading !!! static inline u32 fifo_get_held_qnt( struct fifo_s *pf) { return (pf->cntHeld - pf->cntFree); } #endif //-USE_FIFO_DEBUG #ifdef __cplusplus } #endif #endif //__fifo_h