|
Packit |
c32a2d |
/*
|
|
Packit |
c32a2d |
SFIFO 1.3 Simple portable lock-free FIFO
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
(c) 2000-2002, David Olofson - free software under the terms of the LGPL 2.1
|
|
Packit |
c32a2d |
*/
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/*
|
|
Packit |
c32a2d |
* Platform support:
|
|
Packit |
c32a2d |
* gcc / Linux / x86: Works
|
|
Packit |
c32a2d |
* gcc / Linux / x86 kernel: Works
|
|
Packit |
c32a2d |
* gcc / FreeBSD / x86: Works
|
|
Packit |
c32a2d |
* gcc / NetBSD / x86: Works
|
|
Packit |
c32a2d |
* gcc / Mac OS X / PPC: Works
|
|
Packit |
c32a2d |
* gcc / Win32 / x86: Works
|
|
Packit |
c32a2d |
* Borland C++ / DOS / x86RM: Works
|
|
Packit |
c32a2d |
* Borland C++ / Win32 / x86PM16: Untested
|
|
Packit |
c32a2d |
* ? / Various Un*ces / ?: Untested
|
|
Packit |
c32a2d |
* ? / Mac OS / PPC: Untested
|
|
Packit |
c32a2d |
* gcc / BeOS / x86: Untested
|
|
Packit |
c32a2d |
* gcc / BeOS / PPC: Untested
|
|
Packit |
c32a2d |
* ? / ? / Alpha: Untested
|
|
Packit |
c32a2d |
*
|
|
Packit |
c32a2d |
* 1.2: Max buffer size halved, to avoid problems with
|
|
Packit |
c32a2d |
* the sign bit...
|
|
Packit |
c32a2d |
*
|
|
Packit |
c32a2d |
* 1.3: Critical buffer allocation bug fixed! For certain
|
|
Packit |
c32a2d |
* requested buffer sizes, older version would
|
|
Packit |
c32a2d |
* allocate a buffer of insufficient size, which
|
|
Packit |
c32a2d |
* would result in memory thrashing. (Amazing that
|
|
Packit |
c32a2d |
* I've manage to use this to the extent I have
|
|
Packit |
c32a2d |
* without running into this... *heh*)
|
|
Packit |
c32a2d |
*/
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#ifndef _SFIFO_H_
|
|
Packit |
c32a2d |
#define _SFIFO_H_
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#ifdef __cplusplus
|
|
Packit |
c32a2d |
extern "C" {
|
|
Packit |
c32a2d |
#endif
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#include <errno.h>
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* Defining SFIFO_STATIC and then including the sfifo.c will result in local code. */
|
|
Packit |
c32a2d |
#ifdef SFIFO_STATIC
|
|
Packit |
c32a2d |
#define SFIFO_SCOPE static
|
|
Packit |
c32a2d |
#else
|
|
Packit |
c32a2d |
#define SFIFO_SCOPE
|
|
Packit |
c32a2d |
#endif
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/*------------------------------------------------
|
|
Packit |
c32a2d |
"Private" stuff
|
|
Packit |
c32a2d |
------------------------------------------------*/
|
|
Packit |
c32a2d |
/*
|
|
Packit |
c32a2d |
* Porting note:
|
|
Packit |
c32a2d |
* Reads and writes of a variable of this type in memory
|
|
Packit |
c32a2d |
* must be *atomic*! 'int' is *not* atomic on all platforms.
|
|
Packit |
c32a2d |
* A safe type should be used, and sfifo should limit the
|
|
Packit |
c32a2d |
* maximum buffer size accordingly.
|
|
Packit |
c32a2d |
*/
|
|
Packit |
c32a2d |
typedef int sfifo_atomic_t;
|
|
Packit |
c32a2d |
#ifdef __TURBOC__
|
|
Packit |
c32a2d |
# define SFIFO_MAX_BUFFER_SIZE 0x7fff
|
|
Packit |
c32a2d |
#else /* Kludge: Assume 32 bit platform */
|
|
Packit |
c32a2d |
# define SFIFO_MAX_BUFFER_SIZE 0x7fffffff
|
|
Packit |
c32a2d |
#endif
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
typedef struct sfifo_t
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
char *buffer;
|
|
Packit |
c32a2d |
int size; /* Number of bytes */
|
|
Packit |
c32a2d |
sfifo_atomic_t readpos; /* Read position */
|
|
Packit |
c32a2d |
sfifo_atomic_t writepos; /* Write position */
|
|
Packit |
c32a2d |
} sfifo_t;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#define SFIFO_SIZEMASK(x) ((x)->size - 1)
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/*------------------------------------------------
|
|
Packit |
c32a2d |
API
|
|
Packit |
c32a2d |
------------------------------------------------*/
|
|
Packit |
c32a2d |
SFIFO_SCOPE int sfifo_init(sfifo_t *f, int size);
|
|
Packit |
c32a2d |
SFIFO_SCOPE void sfifo_close(sfifo_t *f);
|
|
Packit |
c32a2d |
SFIFO_SCOPE void sfifo_flush(sfifo_t *f);
|
|
Packit |
c32a2d |
SFIFO_SCOPE int sfifo_write(sfifo_t *f, const void *buf, int len);
|
|
Packit |
c32a2d |
SFIFO_SCOPE int sfifo_read(sfifo_t *f, void *buf, int len);
|
|
Packit |
c32a2d |
#define sfifo_used(x) (((x)->writepos - (x)->readpos) & SFIFO_SIZEMASK(x))
|
|
Packit |
c32a2d |
#define sfifo_space(x) ((x)->size - 1 - sfifo_used(x))
|
|
Packit |
c32a2d |
#define sfifo_size(x) ((x)->size - 1)
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#ifdef __cplusplus
|
|
Packit |
c32a2d |
};
|
|
Packit |
c32a2d |
#endif
|
|
Packit |
c32a2d |
#endif
|