package jasync;

import java.io.EOFException;
import java.io.ObjectOutputStream;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Helper class that serializes messages and writes them to a socket.
 */
public class OutputThread extends Thread {
    /**
     * Output queue. Messages found here will be sent to the network.
     */
    BlockingQueue<Message> outQueue;

    /**
     * From the socket.
     */
    ObjectOutputStream oOutput;

    /**
     * Remote peer.
     */
    Peer peer;

    /**
     * Constructor. Doesn't change state anywhere else.
     * @param peer Peer instance from the handshake.
     * @param oOutput ObjectOutputStream created from the socket.
     * @param outQueue Queue for outgoing messages.
     */
    public OutputThread (Peer peer, ObjectOutputStream oOutput,
			 BlockingQueue<Message> outQueue) {
	this.oOutput = oOutput;
	this.outQueue = outQueue;
	this.peer = peer;
    }

    /**
     * Blocking write loop. Blocks until a Message is available from the queue,
     * then writes it to the socket's output.
     */
    public void run () {
	try {
	    while (true) {
		oOutput.writeObject(outQueue.take());
	    }
	}
	catch (SocketException e) {
	    /* Someone has closed the socket out from under us. The timing
	       is a bit unlikely, but I can't not test for it. That would
	       be crazy. */
	    return;
	}
	catch (InterruptedException e) {
	    /* local thread has requested that we shut down, someone else
	       will clean up */
	    return;		
	}
	catch (Throwable e) {
	    /* basically anything that happens is cause for a disconnect */
	    e.printStackTrace();
	    return;
	}
    }
}

