I am trying to implement a threaded circular buffer with PipedInputStream & PipedOutputStream but it is locking everytime when I get to mHead.write in the Decoder runnable. I thought there was no chance for deadlocks when using separate threads.
private class DecoderTask implements Runnable{
@Override
public void run() {
while(!mStop){
try {
Log.d(TAG,"trying to write");
mHead.write(decode( 0, 1000));
mHead.flush();
Log.d(TAG,"Decoded");
} catch (DecoderException e) {
Log.e(TAG,e.toString());
} catch (IOException e) {
Log.e(TAG,e.toString());
}
}
}
}
private class WriteTask implements Runnable{
@Override
public void run() {
while(!mStop){
try {
Log.d(TAG,"trying to read");
int read = mTail.read(mByteSlave, 0, mByteSlave.length);
mAudioTrack.flush();
mAudioTrack.write(mByteSlave,0,read);
Log.d(TAG,"read");
} catch (IOException e) {
Log.e(TAG,e.toString());
}
}
}
}
//in some function
mTail = new PipedInputStream();
mHead = new PipedOutputStream(mTail);
mByteSlave = new byte[BUF];
mT1 = new Thread(new DecoderTask(), "Reader");
mT2 = new Thread(new WriteTask(), "Writer");
mT1.start();
mT2.start();
return;
edit: here is the full source for my service http://pastie.org/1179792
logcat prints out :
trying to read
trying to write
The program doesn't block, it's just very very slow and inefficient. It uses 100% CPU. The problem is if (mTail.available() >= mByteSlave.length)
- this will return false in most cases, and so you get a busy loop in this thread. If you can get rid of this, do it. Then this problem is solved. If you can't, it gets more complicated...
There is another problem: PipedInputStream.read
returns an int. You need to use:
int len = mTail.read(mByteSlave, 0, mByteSlave.length);
mAudioTrack.write(mByteSlave, 0, len);
Other than that, I couldn't find anything wrong in this code. My complete test case looks like this:
import java.io.*;
public class Test2 {
PipedOutputStream mHead;
PipedInputStream mTail;
byte[] mByteSlave = new byte[1024];
boolean mStop;
public static void main(String... ar) throws Exception {
new Test2().run();
}
void run() throws Exception {
mTail = new PipedInputStream();
mHead = new PipedOutputStream(mTail);
Thread mT1 = new Thread(new DecoderTask(), "Reader");
Thread mT2 = new Thread(new WriteTask(), "Writer");
mT1.start();
mT2.start();
}
class DecoderTask implements Runnable {
public void run() {
while (!mStop) {
try {
mHead.write(new byte[3000]);
mHead.flush();
System.out.println("decoded 3000");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class WriteTask implements Runnable {
public void run() {
while (!mStop) {
try {
int len = mTail.read(mByteSlave, 0, mByteSlave.length);
if (len < 0) break; // EOF
// mAudioTrack.write(mByteSlave, 0, len);
// mAudioTrack.flush();
System.out.println("written " + len);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}