/* * Copyright (C) 2007 The Android Open Source Project * * 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. */ package jackpal.androidterm.emulatorview; /** * A multi-thread-safe produce-consumer byte array. * Only allows one producer and one consumer. */ class ByteQueue { public ByteQueue(int size) { mBuffer = new byte[size]; } public int getBytesAvailable() { synchronized(this) { return mStoredBytes; } } public int read(byte[] buffer, int offset, int length) throws InterruptedException { if (length + offset > buffer.length) { throw new IllegalArgumentException("length + offset > buffer.length"); } if (length < 0) { throw new IllegalArgumentException("length < 0"); } if (length == 0) { return 0; } synchronized(this) { while (mStoredBytes == 0) { wait(); } int totalRead = 0; int bufferLength = mBuffer.length; boolean wasFull = bufferLength == mStoredBytes; while (length > 0 && mStoredBytes > 0) { int oneRun = Math.min(bufferLength - mHead, mStoredBytes); int bytesToCopy = Math.min(length, oneRun); System.arraycopy(mBuffer, mHead, buffer, offset, bytesToCopy); mHead += bytesToCopy; if (mHead >= bufferLength) { mHead = 0; } mStoredBytes -= bytesToCopy; length -= bytesToCopy; offset += bytesToCopy; totalRead += bytesToCopy; } if (wasFull) { notify(); } return totalRead; } } /** * Attempt to write the specified portion of the provided buffer to * the queue. Returns the number of bytes actually written to the queue; * it is the caller's responsibility to check whether all of the data * was written and repeat the call to write() if necessary. */ public int write(byte[] buffer, int offset, int length) throws InterruptedException { if (length + offset > buffer.length) { throw new IllegalArgumentException("length + offset > buffer.length"); } if (length < 0) { throw new IllegalArgumentException("length < 0"); } if (length == 0) { return 0; } synchronized(this) { int bufferLength = mBuffer.length; boolean wasEmpty = mStoredBytes == 0; while(bufferLength == mStoredBytes) { wait(); } int tail = mHead + mStoredBytes; int oneRun; if (tail >= bufferLength) { tail = tail - bufferLength; oneRun = mHead - tail; } else { oneRun = bufferLength - tail; } int bytesToCopy = Math.min(oneRun, length); System.arraycopy(buffer, offset, mBuffer, tail, bytesToCopy); offset += bytesToCopy; mStoredBytes += bytesToCopy; if (wasEmpty) { notify(); } return bytesToCopy; } } private byte[] mBuffer; private int mHead; private int mStoredBytes; }