Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/XRDP/common/   (X11 Server Version 0.10.6.1©)  Datei vom 7.6.2026 mit Größe 7 kB image not shown  

Quelle  fifo.c

  Sprache: C
 

/**
 * xrdp: A Remote Desktop Protocol server.
 *
 * Copyright (C) Matt Burt 2023
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * @file    common/fifo.c
 * @brief   Fifo for storing generic pointers
 *
 * Defines an unbounded FIFO-queue for void * pointers
 *
 * The stored pointers are called 'items' below.
 *
 * Items are stored in groups called 'chunks'. Chunks are linked together
 * in a chain:-
 *
 * +-------------+    +--------+    +--------+    +--------+
 * | first_chunk |--->|  next  |--->|  next  |--->|  NULL  |<-+
 * | last_chunk  |-+  +--------+    +--------+    +--------+  |
 * | . . .       | |  | item.0 |    | item.0 |    | item.0 |  |
 * +-------------+ |  |   ...  |    |   ...  |    |   ...  |  |
 *                 |  | item.n |    | item.n |    | item.n |  |
 *                 |  +--------+    +--------+    +--------+  |
 *                 |                                          |
 *                 +------------------------------------------+
 *
 * This allows items to be added to the FIFO by allocating blocks
 * as each one fills up.
 *
 * The code to read from the FIFO de-allocates blocks as each one is
 * consumed.
 *
 * There is always at least one chunk in the FIFO.
 */



#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif

#include <stdlib.h>

#include "fifo.h"

#define ITEMS_PER_CHUNK 31

struct chunk
{
    struct chunk *next;
    void *items[ITEMS_PER_CHUNK];
};

struct fifo
{
    struct chunk *first_chunk;
    struct chunk *last_chunk;
    /** Next address to write in 'last_chunk' */
    unsigned short writer;
    /** Next address to read in 'first_chunk' */
    unsigned short reader;
    /** Item destructor function, or NULL */
    fifo_item_destructor item_destructor;
};

/*****************************************************************************/

struct fifo *
fifo_create(fifo_item_destructor item_destructor)
{
    struct fifo *result = NULL;
    struct chunk *cptr = (struct chunk *)malloc(sizeof(struct chunk));
    if (cptr != NULL)
    {
        /* 'next' pointer in last block is always NULL */
        cptr->next = NULL;
        result = (struct fifo *)malloc(sizeof(struct fifo));
        if (result == NULL)
        {
            free(cptr);
        }
        else
        {
            result->first_chunk = cptr;
            result->last_chunk = cptr;
            result->writer = 0;
            result->reader = 0;
            result->item_destructor = item_destructor;
        }
    }
    return result;
}

/*****************************************************************************/
/**
 * Internal function to call the destructor function on all items in the fifo
 *
 * @param self fifo. Can't be NULL
 * @param closure Additional argument to destructor function
 */

static void
call_item_destructor(struct fifo *self, void *closure)
{
    if (self->item_destructor != NULL)
    {
        struct chunk *cptr = self->first_chunk;
        unsigned int i = self->reader;

        // Process all the chunks up to the last one
        while (cptr != self->last_chunk)
        {
            (*self->item_destructor)(cptr->items[i++], closure);
            if (i == ITEMS_PER_CHUNK)
            {
                cptr = cptr->next;
                i = 0;
            }
        }

        // Process all the items in the last chunk
        while (i < self->writer)
        {
            (*self->item_destructor)(cptr->items[i++], closure);
        }
    }
}


/*****************************************************************************/
void
fifo_delete(struct fifo *self, void *closure)
{
    if (self != NULL)
    {
        call_item_destructor(self, closure);

        // Now free all the chunks
        struct chunk *cptr = self->first_chunk;
        while (cptr != NULL)
        {
            struct chunk *next = cptr->next;
            free(cptr);
            cptr = next;
        }

        free(self);
    }
}


/*****************************************************************************/
void
fifo_clear(struct fifo *self, void *closure)
{
    if (self != NULL)
    {
        call_item_destructor(self, closure);

        // Now free all the chunks except the last one
        struct chunk *cptr = self->first_chunk;
        while (cptr->next != NULL)
        {
            struct chunk *next = cptr->next;
            free(cptr);
            cptr = next;
        }

        // Re-initialise fifo fields
        self->first_chunk = cptr;
        self->last_chunk = cptr;
        self->reader = 0;
        self->writer = 0;
    }
}

/*****************************************************************************/
int
fifo_add_item(struct fifo *self, void *item)
{
    int rv = 0;
    if (self != NULL && item != NULL)
    {
        if (self->writer == ITEMS_PER_CHUNK)
        {
            // Add another chunk to the chain
            struct chunk *cptr;
            cptr = (struct chunk *)malloc(sizeof(struct chunk));
            if (cptr == NULL)
            {
                return 0;
            }
            cptr->next = NULL;
            self->last_chunk->next = cptr;
            self->last_chunk = cptr;
            self->writer = 0;
        }

        self->last_chunk->items[self->writer++] = item;
        rv = 1;
    }
    return rv;
}

/*****************************************************************************/
void *
fifo_remove_item(struct fifo *self)
{
    void *item = NULL;
    if (self != NULL)
    {
        // More than one chunk in the fifo?
        if (self->first_chunk != self->last_chunk)
        {
            /* We're not reading the last chunk. There
             * must be something in the fifo */

            item = self->first_chunk->items[self->reader++];

            /* At the end of this chunk? */
            if (self->reader == ITEMS_PER_CHUNK)
            {
                struct chunk *old_chunk = self->first_chunk;
                self->first_chunk = old_chunk->next;
                free(old_chunk);
                self->reader = 0;
            }
        }
        else if (self->reader < self->writer)
        {
            /* We're reading the last chunk */
            item = self->first_chunk->items[self->reader++];
            if (self->reader == self->writer)
            {
                // fifo is now empty. We can reset the pointers
                // to prevent unnecessary allocations in the future.
                self->reader = 0;
                self->writer = 0;
            }
        }
    }
    return item;
}

/*****************************************************************************/

int
fifo_is_empty(struct fifo *self)
{
    return (self == NULL ||
            (self->first_chunk == self->last_chunk &&
             self->reader == self->writer));
}

Messung V0.5 in Prozent
C=97 H=76 G=86

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-07-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.