From: Arran Cudbard-Bell Date: Sat, 26 Nov 2016 15:28:52 +0000 (-0500) Subject: Document fifo functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2eb8ebff4a51bcd6e25bdb689e728887701a6a7;p=thirdparty%2Ffreeradius-server.git Document fifo functions and move freeing to a talloc destructor --- diff --git a/src/include/libradius.h b/src/include/libradius.h index b467df4f624..7d046489f82 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -523,7 +523,6 @@ void NEVER_RETURNS _fr_exit_now(char const *file, int line, int status); typedef struct fr_fifo_t fr_fifo_t; typedef void (*fr_fifo_free_t)(void *); fr_fifo_t *fr_fifo_create(TALLOC_CTX *ctx, int max_entries, fr_fifo_free_t freeNode); -void fr_fifo_free(fr_fifo_t *fi); int fr_fifo_push(fr_fifo_t *fi, void *data); void *fr_fifo_pop(fr_fifo_t *fi); void *fr_fifo_peek(fr_fifo_t *fi); diff --git a/src/lib/fifo.c b/src/lib/fifo.c index 3e8af1d4583..f9e4b130946 100644 --- a/src/lib/fifo.c +++ b/src/lib/fifo.c @@ -16,7 +16,7 @@ /** * @file lib/fifo.c - * @brief Non-thread-safe fifo (FIFO) implementation, based on hash tables. + * @brief Non-thread-safe fifo (FIFO) implementation. * * @copyright 2005,2006 The FreeRADIUS server project * @copyright 2005 Alan DeKok @@ -26,37 +26,23 @@ RCSID("$Id$") #include struct fr_fifo_t { - unsigned int num; - unsigned int first, last; - unsigned int max; - fr_fifo_free_t free_node; + unsigned int num; //!< How many elements exist in the fifo. + unsigned int first, last; //!< Head and tail indexes for the fifo. + unsigned int max; //!< How many elements were created in the fifo. + fr_fifo_free_t free_node; //!< Function to call to free nodes when the fifo is freed. void *data[1]; }; - -fr_fifo_t *fr_fifo_create(TALLOC_CTX *ctx, int max, fr_fifo_free_t free_node) -{ - fr_fifo_t *fi; - - if ((max < 2) || (max > (1024 * 1024))) return NULL; - - fi = talloc_zero_size(ctx, (sizeof(*fi) + (sizeof(fi->data[0])*max))); - if (!fi) return NULL; - talloc_set_type(fi, fr_fifo_t); - - fi->max = max; - fi->free_node = free_node; - - return fi; -} - -void fr_fifo_free(fr_fifo_t *fi) +/** Free a fifo and optionally, any data still enqueued + * + * @param[in] fi to free. + * @return 0 + */ +static int _fifo_free(fr_fifo_t *fi) { unsigned int i; - if (!fi) return; - if (fi->free_node) { for (i = 0 ; i < fi->num; i++) { unsigned int element; @@ -72,22 +58,70 @@ void fr_fifo_free(fr_fifo_t *fi) } memset(fi, 0, sizeof(*fi)); - talloc_free(fi); + + return 0; } +/** Create a fifo queue + * + * The first element enqueued will be the first to be dequeued. + * + * @note The created fifo does not provide any thread synchronisation functionality + * such as mutexes. If multiple threads are enqueueing and dequeueing data + * the callers must synchronise their access. + * + * @param[in] ctx to allocate fifo array in. + * @param[in] max The maximum number of elements allowed. + * @param[in] free_node Function to use to free node data if the fifo is freed. + * @return + * - A new fifo queue. + * - NULL on error. + */ +fr_fifo_t *fr_fifo_create(TALLOC_CTX *ctx, int max, fr_fifo_free_t free_node) +{ + fr_fifo_t *fi; + + if ((max < 2) || (max > (1024 * 1024))) return NULL; + + fi = talloc_zero_size(ctx, (sizeof(*fi) + (sizeof(fi->data[0])*max))); + if (!fi) return NULL; + talloc_set_type(fi, fr_fifo_t); + talloc_set_destructor(fi, _fifo_free); + + fi->max = max; + fi->free_node = free_node; + + return fi; +} + +/** Push data onto the fifo + * + * @param[in] fi FIFO to push data onto. + * @param[in] data to push. + * @return + * - 0 on success. + * - -1 on error. + */ int fr_fifo_push(fr_fifo_t *fi, void *data) { - if (!fi || !data) return 0; + if (!fi || !data) return -1; - if (fi->num >= fi->max) return 0; + if (fi->num >= fi->max) return -1; fi->data[fi->last++] = data; if (fi->last >= fi->max) fi->last = 0; fi->num++; - return 1; + return 0; } +/** Pop data off of the fifo + * + * @param[in] fi FIFO to pop data from. + * @return + * - The data popped. + * - NULL if the queue is empty. + */ void *fr_fifo_pop(fr_fifo_t *fi) { void *data; @@ -104,6 +138,13 @@ void *fr_fifo_pop(fr_fifo_t *fi) return data; } +/** Examine the next element that would be popped + * + * @param[in] fi FIFO to peek at. + * @return + * - The data at the head of the queue + * - NULL if the queue is empty. + */ void *fr_fifo_peek(fr_fifo_t *fi) { if (!fi || (fi->num == 0)) return NULL; @@ -111,6 +152,11 @@ void *fr_fifo_peek(fr_fifo_t *fi) return fi->data[fi->first]; } +/** Return the number of elements in the fifo queue + * + * @param[in] fi FIFO to count elements in. + * @return the number of elements + */ unsigned int fr_fifo_num_elements(fr_fifo_t *fi) { if (!fi) return 0; @@ -141,7 +187,7 @@ int main(int argc, char **argv) for (i = 0; i < SPLIT; i++) { array[COUNT % MAX] = COUNT; - if (!fr_fifo_push(fi, &array[COUNT % MAX])) { + if (fr_fifo_push(fi, &array[COUNT % MAX]) < 0) { fprintf(stderr, "%d %d\tfailed pushing %d\n", j, i, COUNT); fr_exit(2); @@ -189,7 +235,7 @@ int main(int argc, char **argv) } } - fr_fifo_free(fi); + talloc_free(fi); fr_exit(0); }