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