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 }