1 /// Translated from C to D
2 module soundio.ring_buffer;
3 
4 extern(C): @nogc: nothrow: __gshared:
5 import core.stdc.config: c_long, c_ulong;
6 
7 import soundio.api: SoundIoRingBuffer;
8 import soundio.soundio_private;
9 import soundio.util;
10 import soundio.os;
11 import soundio.atomics;
12 
13 import core.stdc.stdlib;
14 import core.atomic;
15 
16 package:
17 
18 struct SoundIoRingBufferImpl {
19     @disable this();
20     @disable this(this);
21     private:
22     SoundIoOsMirroredMemory mem;
23     shared(size_t) write_offset; // was: SoundIoAtomicULong, but no 64-bit atomics supported on 32-bit windows
24     shared(size_t) read_offset; // ditto
25     int capacity;
26 }
27 
28 SoundIoRingBuffer* soundio_ring_buffer_create(SoundIo* soundio, int requested_capacity) {
29     SoundIoRingBuffer* rb = cast(SoundIoRingBuffer*) ALLOCATE!SoundIoRingBufferImpl(1);
30 
31     assert(requested_capacity > 0);
32 
33     if (!rb) {
34         soundio_ring_buffer_destroy(rb);
35         return null;
36     }
37 
38     if (soundio_ring_buffer_init(rb, requested_capacity)) {
39         soundio_ring_buffer_destroy(rb);
40         return null;
41     }
42 
43     return rb;
44 }
45 
46 void soundio_ring_buffer_destroy(SoundIoRingBuffer* rb) {
47     if (!rb)
48         return;
49 
50     soundio_ring_buffer_deinit(rb);
51 
52     free(rb);
53 }
54 
55 int soundio_ring_buffer_capacity(SoundIoRingBuffer* rb) {
56     return (cast(SoundIoRingBufferImpl*)rb).capacity;
57 }
58 
59 char* soundio_ring_buffer_write_ptr(SoundIoRingBuffer* rb) {
60     const write_offset = SOUNDIO_ATOMIC_LOAD((cast(SoundIoRingBufferImpl*)rb).write_offset);
61     return (cast(SoundIoRingBufferImpl*)rb).mem.address + (write_offset % (cast(SoundIoRingBufferImpl*)rb).capacity);
62 }
63 
64 void soundio_ring_buffer_advance_write_ptr(SoundIoRingBuffer* rb, int count) {
65     SOUNDIO_ATOMIC_FETCH_ADD((cast(SoundIoRingBufferImpl*)rb).write_offset, count);
66     assert(soundio_ring_buffer_fill_count(rb) >= 0);
67 }
68 
69 char* soundio_ring_buffer_read_ptr(SoundIoRingBuffer* rb) {
70     const read_offset = SOUNDIO_ATOMIC_LOAD((cast(SoundIoRingBufferImpl*)rb).read_offset);
71     return (cast(SoundIoRingBufferImpl*)rb).mem.address + (read_offset % (cast(SoundIoRingBufferImpl*)rb).capacity);
72 }
73 
74 void soundio_ring_buffer_advance_read_ptr(SoundIoRingBuffer* rb, int count) {
75     SOUNDIO_ATOMIC_FETCH_ADD((cast(SoundIoRingBufferImpl*)rb).read_offset, count);
76     assert(soundio_ring_buffer_fill_count(rb) >= 0);
77 }
78 
79 int soundio_ring_buffer_fill_count(SoundIoRingBuffer* rb) {
80     // Whichever offset we load first might have a smaller value. So we load
81     // the read_offset first.
82     auto read_offset = SOUNDIO_ATOMIC_LOAD((cast(SoundIoRingBufferImpl*)rb).read_offset);
83     auto write_offset = SOUNDIO_ATOMIC_LOAD((cast(SoundIoRingBufferImpl*)rb).write_offset);
84     int count = cast(int) (write_offset - read_offset);
85     assert(count >= 0);
86     assert(count <= (cast(SoundIoRingBufferImpl*)rb).capacity);
87     return count;
88 }
89 
90 int soundio_ring_buffer_free_count(SoundIoRingBuffer* rb) {
91     return (cast(SoundIoRingBufferImpl*)rb).capacity - soundio_ring_buffer_fill_count(rb);
92 }
93 
94 void soundio_ring_buffer_clear(SoundIoRingBuffer* rb) {
95     auto read_offset = SOUNDIO_ATOMIC_LOAD((cast(SoundIoRingBufferImpl*)rb).read_offset);
96     SOUNDIO_ATOMIC_STORE((cast(SoundIoRingBufferImpl*)rb).write_offset, read_offset);
97 }
98 
99 int soundio_ring_buffer_init(SoundIoRingBuffer* rb, int requested_capacity) {
100     if (auto err = soundio_os_init_mirrored_memory(&(cast(SoundIoRingBufferImpl*)rb).mem, requested_capacity))
101         return err;
102     SOUNDIO_ATOMIC_STORE((cast(SoundIoRingBufferImpl*)rb).write_offset, 0);
103     SOUNDIO_ATOMIC_STORE((cast(SoundIoRingBufferImpl*)rb).read_offset, 0);
104     (cast(SoundIoRingBufferImpl*)rb).capacity = cast(int) (cast(SoundIoRingBufferImpl*)rb).mem.capacity;
105 
106     return 0;
107 }
108 
109 void soundio_ring_buffer_deinit(SoundIoRingBuffer* rb) {
110     soundio_os_deinit_mirrored_memory(&(cast(SoundIoRingBufferImpl*)rb).mem);
111 }