Back out change adding Looper. Using own queue is better because its

length can be tested and there's no race condition (between the looper
being available and the parent thread wanting to post messages) when
the constructor inits the queue.
This commit is contained in:
ehouse 2010-01-16 18:56:32 +00:00
parent 5c183acb5e
commit 69c8577dcb
2 changed files with 115 additions and 124 deletions

View file

@ -51,7 +51,6 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable {
private Intent m_resultIntent = null;
private JNIThread m_jniThread;
private JNIThread m_jniThread_pending;
public class TimerRunnable implements Runnable {
private int m_gamePtr;
@ -65,10 +64,8 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable {
}
public void run() {
m_timers[m_why] = null;
if ( null != m_jniThread ) {
m_jniThread.handle( JNICmd.CMD_TIMER_FIRED,
m_jniThread.handle( JNICmd.CMD_TIMER_FIRED,
m_why, m_when, m_handle );
}
}
}
@ -158,26 +155,22 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable {
m_prefs, null, dictBytes );
}
m_jniThread_pending = new
m_jniThread = new
JNIThread( m_jniGamePtr,
new Handler() {
public void handleMessage( Message msg ) {
Utils.logf( "handleMessage() called" );
switch( msg.what ) {
case JNIThread.RUNNING:
m_jniThread = m_jniThread_pending;
m_view.startHandling( m_jniThread,
m_jniGamePtr,
m_gi );
m_jniThread.handle( JNICmd.CMD_DO );
break;
case JNIThread.DRAW:
m_view.invalidate();
break;
}
}
} );
m_jniThread_pending.start();
m_jniThread.start();
m_view.startHandling( m_jniThread, m_jniGamePtr, m_gi );
m_jniThread.handle( JNICmd.CMD_DO );
Utils.logf( "BoardActivity::onCreate() done" );
} // onCreate
@ -285,10 +278,8 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable {
handled = false;
}
if ( handled && cmd != JNIThread.JNICmd.CMD_NONE ) {
if ( null != m_jniThread ) {
m_jniThread.handle( cmd );
}
if ( handled && cmd != JNIThread.JNICmd.CMD_NONE ) {
m_jniThread.handle( cmd );
}
return handled;
@ -433,7 +424,7 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable {
public boolean engineProgressCallback()
{
return null != m_jniThread && !m_jniThread.busy();
return ! m_jniThread.busy();
}
public String getUserString( int stringCode )

View file

@ -9,7 +9,6 @@ import java.lang.InterruptedException;
import java.util.concurrent.LinkedBlockingQueue;
import android.os.Handler;
import android.os.Message;
import android.os.Looper;
public class JNIThread extends Thread {
@ -30,26 +29,36 @@ public class JNIThread extends Thread {
CMD_HINT,
CMD_NEXT_HINT,
CMD_VALUES,
CMD_STOP,
};
public static final int RUNNING = 1;
public static final int DRAW = 2;
private boolean m_stopped = false;
private int m_jniGamePtr;
private Handler m_parentHandler;
private Handler m_loopHandler;
private boolean[] m_barr = new boolean[1]; // scratch boolean
private Handler m_handler;
LinkedBlockingQueue<QueueElem> m_queue;
private class QueueElem {
protected QueueElem( JNICmd cmd, Object[] args )
{
m_cmd = cmd; m_args = args;
}
JNICmd m_cmd;
Object[] m_args;
}
public JNIThread( int gamePtr, Handler handler ) {
Utils.logf( "in JNIThread()" );
m_jniGamePtr = gamePtr;
m_parentHandler = handler;
m_handler = handler;
m_queue = new LinkedBlockingQueue<QueueElem>();
}
public void waitToStop() {
handle( JNICmd.CMD_STOP );
m_stopped = true;
handle( JNICmd.CMD_NONE ); // tickle it
try {
join();
} catch ( java.lang.InterruptedException ie ) {
@ -58,10 +67,9 @@ public class JNIThread extends Thread {
}
public boolean busy()
{
// HTF to I tell if my queue has anything in it. Do I have to
// keep a counter? Which means synchronizing...
return false;
{ // synchronize this!!!
int siz = m_queue.size();
return siz > 0;
}
private boolean toggleTray() {
@ -77,111 +85,103 @@ public class JNIThread extends Thread {
public void run()
{
Looper.prepare();
m_loopHandler = new Handler() {
public void handleMessage( Message msg ) {
boolean draw = false;
Object[] args = (Object[])msg.obj;
switch( JNICmd.values()[msg.what] ) {
boolean[] barr = new boolean[1]; // scratch boolean
while ( !m_stopped ) {
QueueElem elem;
Object[] args;
try {
elem = m_queue.take();
} catch ( InterruptedException ie ) {
Utils.logf( "interrupted; killing thread" );
break;
}
boolean draw = false;
args = elem.m_args;
switch( elem.m_cmd ) {
case CMD_DRAW:
draw = true;
break;
case CMD_DO:
draw = XwJNI.server_do( m_jniGamePtr );
break;
case CMD_DRAW:
draw = true;
break;
case CMD_DO:
draw = XwJNI.server_do( m_jniGamePtr );
break;
case CMD_PEN_DOWN:
draw = XwJNI.board_handlePenDown( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue(),
m_barr );
break;
case CMD_PEN_MOVE:
draw = XwJNI.board_handlePenMove( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue() );
break;
case CMD_PEN_UP:
draw = XwJNI.board_handlePenUp( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue() );
break;
case CMD_PEN_DOWN:
draw = XwJNI.board_handlePenDown( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue(),
barr );
break;
case CMD_PEN_MOVE:
draw = XwJNI.board_handlePenMove( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue() );
break;
case CMD_PEN_UP:
draw = XwJNI.board_handlePenUp( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue() );
break;
case CMD_COMMIT:
draw = XwJNI.board_commitTurn( m_jniGamePtr );
break;
case CMD_COMMIT:
draw = XwJNI.board_commitTurn( m_jniGamePtr );
break;
case CMD_JUGGLE:
draw = XwJNI.board_juggleTray( m_jniGamePtr );
break;
case CMD_FLIP:
draw = XwJNI.board_flip( m_jniGamePtr );
break;
case CMD_TOGGLE_TRAY:
draw = toggleTray();
break;
case CMD_TOGGLE_TRADE:
draw = XwJNI.board_beginTrade( m_jniGamePtr );
break;
case CMD_UNDO_CUR:
draw = XwJNI.board_replaceTiles( m_jniGamePtr );
break;
case CMD_UNDO_LAST:
XwJNI.server_handleUndo( m_jniGamePtr );
draw = true;
break;
case CMD_JUGGLE:
draw = XwJNI.board_juggleTray( m_jniGamePtr );
break;
case CMD_FLIP:
draw = XwJNI.board_flip( m_jniGamePtr );
break;
case CMD_TOGGLE_TRAY:
draw = toggleTray();
break;
case CMD_TOGGLE_TRADE:
draw = XwJNI.board_beginTrade( m_jniGamePtr );
break;
case CMD_UNDO_CUR:
draw = XwJNI.board_replaceTiles( m_jniGamePtr );
break;
case CMD_UNDO_LAST:
XwJNI.server_handleUndo( m_jniGamePtr );
draw = true;
break;
case CMD_HINT:
XwJNI.board_resetEngine( m_jniGamePtr );
// fallthru
case CMD_NEXT_HINT:
draw = XwJNI.board_requestHint( m_jniGamePtr, false, m_barr );
if ( m_barr[0] ) {
handle( JNICmd.CMD_NEXT_HINT );
}
break;
case CMD_VALUES:
draw = XwJNI.board_toggle_showValues( m_jniGamePtr );
break;
case CMD_TIMER_FIRED:
draw = XwJNI.timerFired( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue(),
((Integer)args[2]).intValue() );
break;
case CMD_STOP:
Looper.myLooper().quit();
break;
}
if ( draw ) {
if ( !XwJNI.board_draw( m_jniGamePtr ) ) {
Utils.logf( "draw not complete" );
}
Message.obtain( m_parentHandler, DRAW ).sendToTarget();
}
case CMD_HINT:
XwJNI.board_resetEngine( m_jniGamePtr );
// fallthru
case CMD_NEXT_HINT:
draw = XwJNI.board_requestHint( m_jniGamePtr, false, barr );
if ( barr[0] ) {
handle( JNICmd.CMD_NEXT_HINT );
}
};
break;
// Safe to use us now
Message.obtain( m_parentHandler, RUNNING ).sendToTarget();
Looper.loop();
case CMD_VALUES:
draw = XwJNI.board_toggle_showValues( m_jniGamePtr );
break;
case CMD_TIMER_FIRED:
draw = XwJNI.timerFired( m_jniGamePtr,
((Integer)args[0]).intValue(),
((Integer)args[1]).intValue(),
((Integer)args[2]).intValue() );
break;
}
if ( draw ) {
if ( !XwJNI.board_draw( m_jniGamePtr ) ) {
Utils.logf( "draw not complete" );
}
Message.obtain( m_handler, DRAW ).sendToTarget();
}
}
Utils.logf( "run exiting" );
} // run
/** Post a cmd to be handled by the JNI thread
*/
public void handle( JNICmd cmd, Object... args )
{
Message message = Message.obtain( m_loopHandler, cmd.ordinal(), args );
message.sendToTarget();
QueueElem elem = new QueueElem( cmd, args );
m_queue.add( elem );
}
}