/* // here's how to do it with a socket final JStem stem = new jStem(); // or whatever Socket s = new Socket("localhost", 5002); NonBlockingInputStream inputStream = new NonBlockingInputStream(s.getInputStream()); OutputStream outputStream = s.getOutputStream(); ((NonBlockingInputStream)inputStream).registerNonBlockingEvent(new StreamEventListener() { public void streamEvent(InputStream stream) { stem.nonBlockingEvent(); } }); // tell the stream where to get I/O stem.SetStream(inputStream, outputStream); // here's how to do it using the I2C code (cross fingers) final JStem stem = new jStem(); // or whatever NonBlockingInputStream inputStream = new NonBlockingInputStream(new FileInputStream("/dev/brainstem")); OutputStream outputStream = new FileOutputStream("/dev/brainstem"); ((NonBlockingInputStream)inputStream).registerNonBlockingEvent(new StreamEventListener() { public void streamEvent(InputStream stream) { stem.nonBlockingEvent(); } }); // tell the stream where to get I/O stem.SetStream(inputStream, outputStream); */ /* show(); import acroname.*; Brainstem b = new Brainstem(); b.setServo(4,2,160); b.getA2D(4,2); b.getDigital(4,1); */ package acroname; import java.io.*; /** A wrapper for Java's input streams which provides for nonblocking reads and provides stream events to a listener. When you construct a NonBlockingInputStream, a background thread is created which constantly reads from the underlying InputStream and loads the result into a buffer. mark(), reset(), and skip() are presently unsupported.
You can perform blocking reads as usual, but you also have the option of performing nonblocking reads where after some specified timeout after which the read returns even if it has not read fully. If data is immediately available, nonblocking reads will return that data even if it's not everything you need, so you may need to read again. You can further do a blocking available() with a timeout.
If you need it, you can register a StreamEventListener which is notified each time
data comes available on the InputStream. This notification will occur from the
underlying Thread, so you want to do your read and not block elsewhere at that point.
*/
public class NonBlockingInputStream extends FilterInputStream
{
StreamEventListener listener;
Object listener_lock = new Object();
public void registerNonBlockingEvent(StreamEventListener listener)
{
synchronized(listener_lock) { this.listener = listener; }
}
public NonBlockingInputStream(InputStream in)
{
this(in, 256, false);
}
public NonBlockingInputStream(InputStream in, int initialBufferSize, boolean useAvailable)
{
super(in);
this.useAvailable = useAvailable;
c = new byte[initialBufferSize];
c2 = new byte[initialBufferSize];
startThread();
}
// CAN WE USE AVAILABLE?
boolean useAvailable = false;
// THE BUFFER
byte[] c; // our character buffer
byte[] c2; // temporary buffer
static final int EMPTY = -1; // indicates nothing there
Object c_lock = new Object(); // lock on this to get access to c
int length; // how much data is available
int offset; // offset into c where data starts
// THE THREAD STATE
int state = READING; // the current state of the startThread
static final int AVAILABLE = 1; // the start thread has made a char available in c and is waiting
// to be notified that the char was read by someone
static final int READING = 0; // the start thread is reading in another char from I/O and
// nothing is available in c
Object state_lock = new Object(); // lock on this to get access to state
// DID THE THREAD DIE?
IOException exception = null; // the thread is fine
Object exception_lock = new Object(); // lock on this to get access to exception
// THE BACKGROUND READING THREAD
public void startThread()
{
new Thread(new Runnable()
{
public void run()
{
while(true)
{
// at this stage we're in READING mode, so we have control of c.
// we try to read in a character, and block until we're successful.
try
{
if (useAvailable)
{
int i = in.available();
if (i > c2.length) c2 = new byte[i];
}
int len = in.read(c2);
System.out.println("In "+len+": ");
for(int x=0;x