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 }