src/util/ring-fifo.c (view raw)
1/* Copyright (c) 2013-2014 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "ring-fifo.h"
7
8#include "util/memory.h"
9
10#ifndef _MSC_VER
11#define ATOMIC_STORE(DST, SRC) __atomic_store_n(&DST, SRC, __ATOMIC_RELEASE)
12#define ATOMIC_LOAD(DST, SRC) DST = __atomic_load_n(&SRC, __ATOMIC_ACQUIRE)
13#else
14// TODO
15#define ATOMIC_STORE(DST, SRC) DST = SRC
16#define ATOMIC_LOAD(DST, SRC) DST = SRC
17#endif
18
19void RingFIFOInit(struct RingFIFO* buffer, size_t capacity, size_t maxalloc) {
20 buffer->data = anonymousMemoryMap(capacity);
21 buffer->capacity = capacity;
22 buffer->maxalloc = maxalloc;
23 RingFIFOClear(buffer);
24}
25
26void RingFIFODeinit(struct RingFIFO* buffer) {
27 mappedMemoryFree(buffer->data, buffer->capacity);
28 buffer->data = 0;
29}
30
31size_t RingFIFOCapacity(const struct RingFIFO* buffer) {
32 return buffer->capacity;
33}
34
35void RingFIFOClear(struct RingFIFO* buffer) {
36 ATOMIC_STORE(buffer->readPtr, buffer->data);
37 ATOMIC_STORE(buffer->writePtr, buffer->data);
38}
39
40size_t RingFIFOWrite(struct RingFIFO* buffer, const void* value, size_t length) {
41 void* data = buffer->writePtr;
42 void* end;
43 ATOMIC_LOAD(end, buffer->readPtr);
44 size_t remaining;
45 if ((intptr_t) data - (intptr_t) buffer->data + buffer->maxalloc >= buffer->capacity) {
46 data = buffer->data;
47 }
48 if (data >= end) {
49 remaining = (intptr_t) buffer->data + buffer->capacity - (intptr_t) data;
50 } else {
51 remaining = (intptr_t) end - (intptr_t) data;
52 }
53 if (remaining <= length) {
54 return 0;
55 }
56 if (value) {
57 memcpy(data, value, length);
58 }
59 ATOMIC_STORE(buffer->writePtr, (void*) ((intptr_t) data + length));
60 return length;
61}
62
63size_t RingFIFORead(struct RingFIFO* buffer, void* output, size_t length) {
64 void* data = buffer->readPtr;
65 void* end;
66 ATOMIC_LOAD(end, buffer->writePtr);
67 size_t remaining;
68 if ((intptr_t) data - (intptr_t) buffer->data + buffer->maxalloc >= buffer->capacity) {
69 data = buffer->data;
70 }
71 if (data > end) {
72 remaining = (intptr_t) buffer->data + buffer->capacity - (intptr_t) data;
73 } else {
74 remaining = (intptr_t) end - (intptr_t) data;
75 }
76 if (remaining <= length) {
77 return 0;
78 }
79 if (output) {
80 memcpy(output, data, length);
81 }
82 ATOMIC_STORE(buffer->readPtr, (void*) ((intptr_t) data + length));
83 return length;
84}