Use LoopingThread for Reader and Writer.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@11 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Communicator.java,v 1.4 2001/05/29 03:27:59 mdb Exp $
|
// $Id: Communicator.java,v 1.5 2001/05/30 23:51:39 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.cocktail.cher.client;
|
package com.samskivert.cocktail.cher.client;
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@ import java.io.*;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import com.samskivert.util.LoopingThread;
|
||||||
import com.samskivert.util.Queue;
|
import com.samskivert.util.Queue;
|
||||||
|
|
||||||
import com.samskivert.cocktail.cher.Log;
|
import com.samskivert.cocktail.cher.Log;
|
||||||
@@ -38,7 +39,7 @@ import com.samskivert.cocktail.cher.util.Codes;
|
|||||||
* - write loop
|
* - write loop
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
class Communicator
|
public class Communicator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new communicator instance which is associated with the
|
* Creates a new communicator instance which is associated with the
|
||||||
@@ -246,52 +247,25 @@ class Communicator
|
|||||||
* things, but the general flow of the reader thread is encapsulated
|
* things, but the general flow of the reader thread is encapsulated
|
||||||
* in this class.
|
* in this class.
|
||||||
*/
|
*/
|
||||||
protected class Reader extends Thread
|
protected class Reader extends LoopingThread
|
||||||
{
|
{
|
||||||
public void run ()
|
protected void willStart ()
|
||||||
{
|
{
|
||||||
|
// first we connect and authenticate with the server
|
||||||
try {
|
try {
|
||||||
// first we connect and authenticate with the server
|
// connect to the server
|
||||||
try {
|
connect();
|
||||||
// connect to the server
|
|
||||||
connect();
|
|
||||||
|
|
||||||
// then authenticate
|
// then authenticate
|
||||||
logon();
|
logon();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.info("Logon failed: " + e);
|
Log.info("Logon failed: " + e);
|
||||||
Log.logStackTrace(e);
|
Log.logStackTrace(e);
|
||||||
// let the observers know that we've failed
|
// let the observers know that we've failed
|
||||||
_client.notifyObservers(Client.CLIENT_FAILED_TO_LOGON, e);
|
_client.notifyObservers(Client.CLIENT_FAILED_TO_LOGON, e);
|
||||||
// and terminate our communicator thread
|
// and terminate our communicator thread
|
||||||
return;
|
shutdown();
|
||||||
}
|
|
||||||
|
|
||||||
// now that we're authenticated, we manage the reading
|
|
||||||
// half of things by continuously reading messages from
|
|
||||||
// the socket and processing them
|
|
||||||
listen();
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
// let the communicator know when we finally go away
|
|
||||||
readerDidExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Informs the reader thread that it's no longer running. The next
|
|
||||||
* time through the read loop, it will exit.
|
|
||||||
*/
|
|
||||||
public synchronized void shutdown ()
|
|
||||||
{
|
|
||||||
_running = false;
|
|
||||||
|
|
||||||
// if we are not the reader thread, then we want to interrupt
|
|
||||||
// the reader thread as it may be blocked listening to the
|
|
||||||
// socket
|
|
||||||
if (Thread.currentThread() != this) {
|
|
||||||
interrupt();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,8 +303,10 @@ class Communicator
|
|||||||
sendMessage(req);
|
sendMessage(req);
|
||||||
|
|
||||||
// now wait for the auth response
|
// now wait for the auth response
|
||||||
|
Log.info("Waiting for auth response.");
|
||||||
AuthResponse rsp = (AuthResponse)receiveMessage();
|
AuthResponse rsp = (AuthResponse)receiveMessage();
|
||||||
AuthResponseData data = rsp.getData();
|
AuthResponseData data = rsp.getData();
|
||||||
|
Log.info("Got auth response: " + data);
|
||||||
|
|
||||||
// if the auth request failed, we want to let the communicator
|
// if the auth request failed, we want to let the communicator
|
||||||
// know by throwing a login exception
|
// know by throwing a login exception
|
||||||
@@ -342,59 +318,59 @@ class Communicator
|
|||||||
logonSucceeded(data);
|
logonSucceeded(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void listen ()
|
// now that we're authenticated, we manage the reading
|
||||||
|
// half of things by continuously reading messages from
|
||||||
|
// the socket and processing them
|
||||||
|
protected void iterate ()
|
||||||
{
|
{
|
||||||
DownstreamMessage msg = null;
|
DownstreamMessage msg = null;
|
||||||
|
|
||||||
while (isRunning()) {
|
try {
|
||||||
try {
|
// read the next message from the socket
|
||||||
// read the next message from the socket
|
msg = receiveMessage();
|
||||||
msg = receiveMessage();
|
|
||||||
|
|
||||||
// process the message
|
// process the message
|
||||||
processMessage(msg);
|
processMessage(msg);
|
||||||
|
|
||||||
} catch (ObjectStreamException ose) {
|
} catch (ObjectStreamException ose) {
|
||||||
Log.warning("Error decoding message: " + ose);
|
Log.warning("Error decoding message: " + ose);
|
||||||
// move on to the next message
|
|
||||||
|
|
||||||
} catch (InterruptedIOException iioe) {
|
} catch (InterruptedIOException iioe) {
|
||||||
// somebody set up us the bomb! we've been interrupted
|
// somebody set up us the bomb! we've been interrupted
|
||||||
// which means that we're being shut down, so we
|
// which means that we're being shut down, so we just
|
||||||
// simply fall through and isRunning() will return
|
// report it and return from iterate() like a good monkey
|
||||||
// false next time through the loop
|
Log.info("Reader thread woken up in time to die.");
|
||||||
Log.info("Reader thread woken up in time to die.");
|
|
||||||
|
|
||||||
} catch (EOFException eofe) {
|
} catch (EOFException eofe) {
|
||||||
Log.info("Connection closed by peer.");
|
Log.info("Connection closed by peer.");
|
||||||
// nothing left for us to do
|
// nothing left for us to do
|
||||||
shutdown();
|
shutdown();
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
// let the communicator know that our connection
|
// let the communicator know that our connection failed
|
||||||
// failed
|
connectionFailed(ioe);
|
||||||
connectionFailed(ioe);
|
// and shut ourselves down
|
||||||
// and shut ourselves down
|
shutdown();
|
||||||
shutdown();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.warning("Error processing message [msg=" + msg +
|
Log.warning("Error processing message [msg=" + msg +
|
||||||
", error=" + e + "].");
|
", error=" + e + "].");
|
||||||
// move on to the next message
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected void didShutdown ()
|
||||||
* Must access _running via this member function to ensure that we
|
|
||||||
* are Chapter 17 compliant.
|
|
||||||
*/
|
|
||||||
protected synchronized boolean isRunning ()
|
|
||||||
{
|
{
|
||||||
return _running;
|
// let the communicator know when we finally go away
|
||||||
|
readerDidExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean _running = true;
|
protected void kick ()
|
||||||
|
{
|
||||||
|
// we want to interrupt the reader thread as it may be blocked
|
||||||
|
// listening to the socket; this is only called if the reader
|
||||||
|
// thread doesn't shut itself down
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,63 +378,44 @@ class Communicator
|
|||||||
* to the <code>Communicator</code> class to do things, but the
|
* to the <code>Communicator</code> class to do things, but the
|
||||||
* general flow of the writer thread is encapsulated in this class.
|
* general flow of the writer thread is encapsulated in this class.
|
||||||
*/
|
*/
|
||||||
protected class Writer extends Thread
|
protected class Writer extends LoopingThread
|
||||||
{
|
{
|
||||||
public void run ()
|
protected void iterate ()
|
||||||
{
|
{
|
||||||
|
// fetch the next message from the queue
|
||||||
|
UpstreamMessage msg = (UpstreamMessage)_msgq.get();
|
||||||
|
|
||||||
|
// if this is a termination message, we're being
|
||||||
|
// requested to exit, so we want to bail now rather
|
||||||
|
// than continuing
|
||||||
|
if (msg instanceof TerminationMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (isRunning()) {
|
// write the message out the socket
|
||||||
// fetch the next message from the queue
|
sendMessage(msg);
|
||||||
UpstreamMessage msg = (UpstreamMessage)_msgq.get();
|
|
||||||
|
|
||||||
// if this is a termination message, we're being
|
} catch (IOException ioe) {
|
||||||
// requested to exit, so we want to bail now rather
|
// let the communicator know if we have any
|
||||||
// than continuing
|
// problems
|
||||||
if (msg instanceof TerminationMessage) {
|
connectionFailed(ioe);
|
||||||
break;
|
// and bail
|
||||||
}
|
shutdown();
|
||||||
|
|
||||||
try {
|
|
||||||
// write the message out the socket
|
|
||||||
sendMessage(msg);
|
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// let the communicator know if we have any
|
|
||||||
// problems
|
|
||||||
connectionFailed(ioe);
|
|
||||||
// and bail
|
|
||||||
shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
writerDidExit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected void didShutdown ()
|
||||||
* Informs the writer thread that it's no longer running. The next
|
|
||||||
* time through the write loop, it will exit.
|
|
||||||
*/
|
|
||||||
public synchronized void shutdown ()
|
|
||||||
{
|
{
|
||||||
_running = false;
|
writerDidExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void kick ()
|
||||||
|
{
|
||||||
// post a bogus message to the outgoing queue to ensure that
|
// post a bogus message to the outgoing queue to ensure that
|
||||||
// the writer thread notices that it's time to go
|
// the writer thread notices that it's time to go
|
||||||
postMessage(new TerminationMessage());
|
postMessage(new TerminationMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Must access _running via this member function to ensure that we
|
|
||||||
* are Chapter 17 compliant.
|
|
||||||
*/
|
|
||||||
protected synchronized boolean isRunning ()
|
|
||||||
{
|
|
||||||
return _running;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean _running = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This is used to terminate the writer thread. */
|
/** This is used to terminate the writer thread. */
|
||||||
|
|||||||
Reference in New Issue
Block a user