aboutsummaryrefslogtreecommitdiffstats
path: root/src/zix/ring.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-16 19:35:21 +0100
committerDavid Robillard <d@drobilla.net>2021-01-16 19:35:21 +0100
commit8952dde02d9d6761ae0cae033600f4a220c8e075 (patch)
tree5715888d4322daea9d29fc2f174d2a623d6085eb /src/zix/ring.c
parent9ab6e66c6ea7230f716b74d62c03fc5d19f56abe (diff)
downloadjalv-master.tar.gz
jalv-master.tar.bz2
jalv-master.zip
Update zixHEADmaster
Diffstat (limited to 'src/zix/ring.c')
-rw-r--r--src/zix/ring.c225
1 files changed, 116 insertions, 109 deletions
diff --git a/src/zix/ring.c b/src/zix/ring.c
index e728a3f..4a4692f 100644
--- a/src/zix/ring.c
+++ b/src/zix/ring.c
@@ -1,5 +1,5 @@
/*
- Copyright 2011 David Robillard <d@drobilla.net>
+ Copyright 2011-2020 David Robillard <d@drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -20,198 +20,205 @@
#include <string.h>
#ifdef HAVE_MLOCK
-# include <sys/mman.h>
-# define ZIX_MLOCK(ptr, size) mlock((ptr), (size))
+# include <sys/mman.h>
+# define ZIX_MLOCK(ptr, size) mlock((ptr), (size))
#elif defined(_WIN32)
-# include <windows.h>
-# define ZIX_MLOCK(ptr, size) VirtualLock((ptr), (size))
+# include <windows.h>
+# define ZIX_MLOCK(ptr, size) VirtualLock((ptr), (size))
#else
-# pragma message("warning: No memory locking, possible RT violations")
-# define ZIX_MLOCK(ptr, size)
+# pragma message("warning: No memory locking, possible RT violations")
+# define ZIX_MLOCK(ptr, size)
#endif
#if defined(_MSC_VER)
-# include <windows.h>
-# define ZIX_READ_BARRIER() MemoryBarrier()
-# define ZIX_WRITE_BARRIER() MemoryBarrier()
+# include <windows.h>
+# define ZIX_READ_BARRIER() MemoryBarrier()
+# define ZIX_WRITE_BARRIER() MemoryBarrier()
#elif defined(__GNUC__)
-# define ZIX_READ_BARRIER() __atomic_thread_fence(__ATOMIC_ACQUIRE)
-# define ZIX_WRITE_BARRIER() __atomic_thread_fence(__ATOMIC_RELEASE)
+# define ZIX_READ_BARRIER() __atomic_thread_fence(__ATOMIC_ACQUIRE)
+# define ZIX_WRITE_BARRIER() __atomic_thread_fence(__ATOMIC_RELEASE)
#else
-# pragma message("warning: No memory barriers, possible SMP bugs")
-# define ZIX_READ_BARRIER()
-# define ZIX_WRITE_BARRIER()
+# pragma message("warning: No memory barriers, possible SMP bugs")
+# define ZIX_READ_BARRIER()
+# define ZIX_WRITE_BARRIER()
#endif
struct ZixRingImpl {
- uint32_t write_head; ///< Read index into buf
- uint32_t read_head; ///< Write index into buf
- uint32_t size; ///< Size (capacity) in bytes
- uint32_t size_mask; ///< Mask for fast modulo
- char* buf; ///< Contents
+ uint32_t write_head; ///< Read index into buf
+ uint32_t read_head; ///< Write index into buf
+ uint32_t size; ///< Size (capacity) in bytes
+ uint32_t size_mask; ///< Mask for fast modulo
+ char* buf; ///< Contents
};
static inline uint32_t
next_power_of_two(uint32_t size)
{
- // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
- size--;
- size |= size >> 1u;
- size |= size >> 2u;
- size |= size >> 4u;
- size |= size >> 8u;
- size |= size >> 16u;
- size++;
- return size;
+ // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ size--;
+ size |= size >> 1u;
+ size |= size >> 2u;
+ size |= size >> 4u;
+ size |= size >> 8u;
+ size |= size >> 16u;
+ size++;
+ return size;
}
ZixRing*
zix_ring_new(uint32_t size)
{
- ZixRing* ring = (ZixRing*)malloc(sizeof(ZixRing));
- ring->write_head = 0;
- ring->read_head = 0;
- ring->size = next_power_of_two(size);
- ring->size_mask = ring->size - 1;
- ring->buf = (char*)malloc(ring->size);
- return ring;
+ ZixRing* ring = (ZixRing*)malloc(sizeof(ZixRing));
+ ring->write_head = 0;
+ ring->read_head = 0;
+ ring->size = next_power_of_two(size);
+ ring->size_mask = ring->size - 1;
+ ring->buf = (char*)malloc(ring->size);
+ return ring;
}
void
zix_ring_free(ZixRing* ring)
{
- free(ring->buf);
- free(ring);
+ if (ring) {
+ free(ring->buf);
+ free(ring);
+ }
}
void
zix_ring_mlock(ZixRing* ring)
{
- ZIX_MLOCK(ring, sizeof(ZixRing));
- ZIX_MLOCK(ring->buf, ring->size);
+ ZIX_MLOCK(ring, sizeof(ZixRing));
+ ZIX_MLOCK(ring->buf, ring->size);
}
void
zix_ring_reset(ZixRing* ring)
{
- ring->write_head = 0;
- ring->read_head = 0;
+ ring->write_head = 0;
+ ring->read_head = 0;
}
static inline uint32_t
read_space_internal(const ZixRing* ring, uint32_t r, uint32_t w)
{
- if (r < w) {
- return w - r;
- } else {
- return (w - r + ring->size) & ring->size_mask;
- }
+ if (r < w) {
+ return w - r;
+ }
+
+ return (w - r + ring->size) & ring->size_mask;
}
uint32_t
zix_ring_read_space(const ZixRing* ring)
{
- return read_space_internal(ring, ring->read_head, ring->write_head);
+ return read_space_internal(ring, ring->read_head, ring->write_head);
}
static inline uint32_t
write_space_internal(const ZixRing* ring, uint32_t r, uint32_t w)
{
- if (r == w) {
- return ring->size - 1;
- } else if (r < w) {
- return ((r - w + ring->size) & ring->size_mask) - 1;
- } else {
- return (r - w) - 1;
- }
+ if (r == w) {
+ return ring->size - 1;
+ }
+
+ if (r < w) {
+ return ((r - w + ring->size) & ring->size_mask) - 1;
+ }
+
+ return (r - w) - 1;
}
uint32_t
zix_ring_write_space(const ZixRing* ring)
{
- return write_space_internal(ring, ring->read_head, ring->write_head);
+ return write_space_internal(ring, ring->read_head, ring->write_head);
}
uint32_t
zix_ring_capacity(const ZixRing* ring)
{
- return ring->size - 1;
+ return ring->size - 1;
}
static inline uint32_t
-peek_internal(const ZixRing* ring, uint32_t r, uint32_t w,
- uint32_t size, void* dst)
+peek_internal(const ZixRing* ring,
+ uint32_t r,
+ uint32_t w,
+ uint32_t size,
+ void* dst)
{
- if (read_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- if (r + size < ring->size) {
- memcpy(dst, &ring->buf[r], size);
- } else {
- const uint32_t first_size = ring->size - r;
- memcpy(dst, &ring->buf[r], first_size);
- memcpy((char*)dst + first_size, &ring->buf[0], size - first_size);
- }
-
- return size;
+ if (read_space_internal(ring, r, w) < size) {
+ return 0;
+ }
+
+ if (r + size < ring->size) {
+ memcpy(dst, &ring->buf[r], size);
+ } else {
+ const uint32_t first_size = ring->size - r;
+ memcpy(dst, &ring->buf[r], first_size);
+ memcpy((char*)dst + first_size, &ring->buf[0], size - first_size);
+ }
+
+ return size;
}
uint32_t
zix_ring_peek(ZixRing* ring, void* dst, uint32_t size)
{
- return peek_internal(ring, ring->read_head, ring->write_head, size, dst);
+ return peek_internal(ring, ring->read_head, ring->write_head, size, dst);
}
uint32_t
zix_ring_read(ZixRing* ring, void* dst, uint32_t size)
{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
+ const uint32_t r = ring->read_head;
+ const uint32_t w = ring->write_head;
- if (peek_internal(ring, r, w, size, dst)) {
- ZIX_READ_BARRIER();
- ring->read_head = (r + size) & ring->size_mask;
- return size;
- }
+ if (peek_internal(ring, r, w, size, dst)) {
+ ZIX_READ_BARRIER();
+ ring->read_head = (r + size) & ring->size_mask;
+ return size;
+ }
- return 0;
+ return 0;
}
uint32_t
zix_ring_skip(ZixRing* ring, uint32_t size)
{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
- if (read_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- ZIX_READ_BARRIER();
- ring->read_head = (r + size) & ring->size_mask;
- return size;
+ const uint32_t r = ring->read_head;
+ const uint32_t w = ring->write_head;
+ if (read_space_internal(ring, r, w) < size) {
+ return 0;
+ }
+
+ ZIX_READ_BARRIER();
+ ring->read_head = (r + size) & ring->size_mask;
+ return size;
}
uint32_t
zix_ring_write(ZixRing* ring, const void* src, uint32_t size)
{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
- if (write_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- if (w + size <= ring->size) {
- memcpy(&ring->buf[w], src, size);
- ZIX_WRITE_BARRIER();
- ring->write_head = (w + size) & ring->size_mask;
- } else {
- const uint32_t this_size = ring->size - w;
- memcpy(&ring->buf[w], src, this_size);
- memcpy(&ring->buf[0], (const char*)src + this_size, size - this_size);
- ZIX_WRITE_BARRIER();
- ring->write_head = size - this_size;
- }
-
- return size;
+ const uint32_t r = ring->read_head;
+ const uint32_t w = ring->write_head;
+ if (write_space_internal(ring, r, w) < size) {
+ return 0;
+ }
+
+ if (w + size <= ring->size) {
+ memcpy(&ring->buf[w], src, size);
+ ZIX_WRITE_BARRIER();
+ ring->write_head = (w + size) & ring->size_mask;
+ } else {
+ const uint32_t this_size = ring->size - w;
+ memcpy(&ring->buf[w], src, this_size);
+ memcpy(&ring->buf[0], (const char*)src + this_size, size - this_size);
+ ZIX_WRITE_BARRIER();
+ ring->write_head = size - this_size;
+ }
+
+ return size;
}