/* * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "synth.h" #include "ringbuffer.h" RingBuffer::RingBuffer() { rd_ix_ = 0; wr_ix_ = 0; } int RingBuffer::BytesAvailable() { return (wr_ix_ - rd_ix_) & (kBufSize - 1); } int RingBuffer::WriteBytesAvailable() { return (rd_ix_ - wr_ix_ - 1) & (kBufSize - 1); } int RingBuffer::Read(int size, uint8_t *bytes) { int rd_ix = rd_ix_; SynthMemoryBarrier(); // read barrier, make sure data is committed before ix int fragment_size = min(size, kBufSize - rd_ix); memcpy(bytes, buf_ + rd_ix, fragment_size); if (size > fragment_size) { memcpy(bytes + fragment_size, buf_, size - fragment_size); } SynthMemoryBarrier(); // full barrier, make sure read commits before updating rd_ix_ = (rd_ix + size) & (kBufSize - 1); return size; } int RingBuffer::Write(const uint8_t *bytes, int size) { int remaining = size; while (remaining > 0) { int rd_ix = rd_ix_; int wr_ix = wr_ix_; int space_available = (rd_ix - wr_ix - 1) & (kBufSize - 1); if (space_available == 0) { struct timespec sleepTime; sleepTime.tv_sec = 0; sleepTime.tv_nsec = 1000000; nanosleep(&sleepTime, NULL); } else { int wr_size = min(remaining, space_available); int fragment_size = min(wr_size, kBufSize - wr_ix); memcpy(buf_ + wr_ix, bytes, fragment_size); if (wr_size > fragment_size) { memcpy(buf_, bytes + fragment_size, wr_size - fragment_size); } SynthMemoryBarrier(); // write barrier, make sure data commits wr_ix_ = (wr_ix + wr_size) & (kBufSize - 1); remaining -= wr_size; bytes += wr_size; } } }