diff --git a/DroidFish/AndroidManifest.xml b/DroidFish/AndroidManifest.xml
index a7045a3..8e45955 100644
--- a/DroidFish/AndroidManifest.xml
+++ b/DroidFish/AndroidManifest.xml
@@ -6,6 +6,8 @@
android:installLocation="auto">
+
+
@@ -45,9 +47,6 @@
android:label="@string/cpu_warning_title">
-
-
-
diff --git a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java
index 15d9a84..4b22e74 100644
--- a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java
+++ b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java
@@ -803,7 +803,7 @@ public class DroidComputerPlayer {
private final synchronized int getReadTimeout() {
boolean needGuiUpdate = depthModified || currMoveModified || pvModified || statsModified;
- int timeout = 1000;
+ int timeout = 2000000000;
if (needGuiUpdate) {
long now = System.currentTimeMillis();
timeout = (int)(lastGUIUpdate + guiUpdateInterval - now + 1);
diff --git a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java
index 6360b05..c531553 100644
--- a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java
+++ b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java
@@ -26,8 +26,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
-import java.util.LinkedList;
-import java.util.List;
import org.petero.droidfish.R;
import android.content.Context;
@@ -45,7 +43,7 @@ public class ExternalEngine extends UCIEngineBase {
private Thread exitThread;
private Thread stdInThread;
private Thread stdErrThread;
- private List inLines;
+ private LocalPipe inLines;
private boolean startedOk;
private boolean isRunning;
@@ -58,7 +56,7 @@ public class ExternalEngine extends UCIEngineBase {
exitThread = null;
stdInThread = null;
stdErrThread = null;
- inLines = new LinkedList();
+ inLines = new LocalPipe();
startedOk = false;
isRunning = false;
}
@@ -120,8 +118,7 @@ public class ExternalEngine extends UCIEngineBase {
if ((ep == null) || Thread.currentThread().isInterrupted())
return;
synchronized (inLines) {
- inLines.add(line);
- inLines.notify();
+ inLines.addLine(line);
if (first) {
startedOk = true;
isRunning = true;
@@ -130,8 +127,8 @@ public class ExternalEngine extends UCIEngineBase {
}
}
} catch (IOException e) {
- return;
}
+ inLines.close();
}
});
stdInThread.start();
@@ -176,26 +173,13 @@ public class ExternalEngine extends UCIEngineBase {
/** @inheritDoc */
@Override
public String readLineFromEngine(int timeoutMillis) {
- try {
- synchronized (inLines) {
- if (inLines.size() == 0) {
- Thread inThread = stdInThread;
- if ((inThread == null) || !inThread.isAlive())
- return null;
- inLines.wait(timeoutMillis);
- }
- }
- synchronized (inLines) {
- if (inLines.size() > 0) {
- String ret = inLines.get(0);
- inLines.remove(0);
-// System.out.printf("Engine -> GUI: %s\n", ret);
- return ret;
- }
- }
- } catch (InterruptedException e) {
+ String ret = inLines.readLine(timeoutMillis);
+ if (ret == null)
+ return null;
+ if (ret.length() > 0) {
+// System.out.printf("Engine -> GUI: %s\n", ret);
}
- return "";
+ return ret;
}
/** @inheritDoc */
diff --git a/DroidFish/src/org/petero/droidfish/engine/LocalPipe.java b/DroidFish/src/org/petero/droidfish/engine/LocalPipe.java
new file mode 100644
index 0000000..82477b8
--- /dev/null
+++ b/DroidFish/src/org/petero/droidfish/engine/LocalPipe.java
@@ -0,0 +1,63 @@
+package org.petero.droidfish.engine;
+
+import java.util.LinkedList;
+
+/** Implements line-based text communication between threads. */
+public class LocalPipe {
+ private LinkedList lines = new LinkedList();
+ private boolean closed = false;
+
+ /** Write a line to the pipe. */
+ public final synchronized void printLine(String format) {
+ String s = String.format(format, new Object[]{});
+ addLine(s);
+ }
+
+ /** Write a line to the pipe. */
+ public final synchronized void printLine(String format, Object ... args) {
+ String s = String.format(format, args);
+ addLine(s);
+ }
+
+ public final synchronized void addLine(String line) {
+ lines.add(line);
+ notify();
+ }
+
+ /** Read a line from the pipe. Returns null on failure. */
+ public final synchronized String readLine() {
+ return readLine(-1);
+ }
+
+ /** Read a line from the pipe. Returns null on failure. Returns empty string on timeout. */
+ public final synchronized String readLine(int timeoutMillis) {
+ if (closed)
+ return null;
+ try {
+ if (lines.isEmpty()) {
+ if (timeoutMillis > 0)
+ wait(timeoutMillis);
+ else
+ wait();
+ }
+ if (lines.isEmpty())
+ return closed ? null : "";
+ String ret = lines.get(0);
+ lines.remove(0);
+ return ret;
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+
+ /** Close pipe. Makes readLine() return null. */
+ public final synchronized void close() {
+ closed = true;
+ notify();
+ }
+
+ /** Return true if writer side has closed the pipe. */
+ public final synchronized boolean isClosed() {
+ return closed;
+ }
+}
diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java
index 46911a6..9d09d6e 100644
--- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java
+++ b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java
@@ -23,11 +23,9 @@ import chess.ComputerPlayer;
import chess.Move;
import chess.Position;
import chess.TextIO;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.Pipe;
import java.util.ArrayList;
+import org.petero.droidfish.engine.LocalPipe;
import org.petero.droidfish.engine.UCIEngineBase;
/**
@@ -46,22 +44,16 @@ public class CuckooChessEngine extends UCIEngineBase {
// Set to true to break out of main loop
private boolean quit;
- private Pipe guiToEngine;
- private Pipe engineToGui;
- private NioInputStream inFromEngine;
+ private LocalPipe guiToEngine;
+ private LocalPipe engineToGui;
private Thread engineThread;
public CuckooChessEngine(Report report) {
pos = null;
moves = new ArrayList();
quit = false;
- try {
- guiToEngine = Pipe.open();
- engineToGui = Pipe.open();
- inFromEngine = new NioInputStream(engineToGui);
- } catch (IOException e) {
- report.reportError(e.getMessage());
- }
+ guiToEngine = new LocalPipe();
+ engineToGui = new LocalPipe();
}
/** @inheritDoc */
@@ -69,9 +61,7 @@ public class CuckooChessEngine extends UCIEngineBase {
protected final void startProcess() {
engineThread = new Thread(new Runnable() {
public void run() {
- NioInputStream in = new NioInputStream(guiToEngine);
- NioPrintStream out = new NioPrintStream(engineToGui);
- mainLoop(in, out);
+ mainLoop(guiToEngine, engineToGui);
}
});
int pMin = Thread.MIN_PRIORITY;
@@ -93,7 +83,7 @@ public class CuckooChessEngine extends UCIEngineBase {
setOption("strength", strength);
}
- private final void mainLoop(NioInputStream is, NioPrintStream os) {
+ private final void mainLoop(LocalPipe is, LocalPipe os) {
String line;
while ((line = is.readLine()) != null) {
handleCommand(line, os);
@@ -103,12 +93,18 @@ public class CuckooChessEngine extends UCIEngineBase {
}
}
+ @Override
+ public void shutDown() {
+ super.shutDown();
+ guiToEngine.close();
+ }
+
/** @inheritDoc */
@Override
public final String readLineFromEngine(int timeoutMillis) {
if ((engineThread != null) && !engineThread.isAlive())
return null;
- String ret = inFromEngine.readLine(timeoutMillis);
+ String ret = engineToGui.readLine(timeoutMillis);
if (ret == null)
return null;
if (ret.length() > 0) {
@@ -121,25 +117,21 @@ public class CuckooChessEngine extends UCIEngineBase {
@Override
public final synchronized void writeLineToEngine(String data) {
// System.out.printf("GUI -> Engine: %s\n", data);
- try {
- String s = data + "\n";
- guiToEngine.sink().write(ByteBuffer.wrap(s.getBytes()));
- } catch (IOException e) {
- }
+ guiToEngine.addLine(data);
}
- private final void handleCommand(String cmdLine, NioPrintStream os) {
+ private final void handleCommand(String cmdLine, LocalPipe os) {
String[] tokens = tokenize(cmdLine);
try {
String cmd = tokens[0];
if (cmd.equals("uci")) {
- os.printf("id name %s%n", ComputerPlayer.engineName);
- os.printf("id author Peter Osterlund%n");
+ os.printLine("id name %s", ComputerPlayer.engineName);
+ os.printLine("id author Peter Osterlund");
DroidEngineControl.printOptions(os);
- os.printf("uciok%n");
+ os.printLine("uciok");
} else if (cmd.equals("isready")) {
initEngine(os);
- os.printf("readyok%n");
+ os.printLine("readyok");
} else if (cmd.equals("setoption")) {
initEngine(os);
StringBuilder optionName = new StringBuilder();
@@ -260,7 +252,7 @@ public class CuckooChessEngine extends UCIEngineBase {
}
}
- private final void initEngine(NioPrintStream os) {
+ private final void initEngine(LocalPipe os) {
if (engine == null) {
engine = new DroidEngineControl(os);
}
diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/DroidEngineControl.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/DroidEngineControl.java
index 926c7c8..896fc20 100644
--- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/DroidEngineControl.java
+++ b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/DroidEngineControl.java
@@ -35,12 +35,14 @@ import java.util.Arrays;
import java.util.List;
import java.util.Random;
+import org.petero.droidfish.engine.LocalPipe;
+
/**
* Control the search thread.
* @author petero
*/
public class DroidEngineControl {
- NioPrintStream os;
+ LocalPipe os;
Thread engineThread;
private final Object threadMutex;
@@ -76,18 +78,18 @@ public class DroidEngineControl {
* This class is responsible for sending "info" strings during search.
*/
static class SearchListener implements Search.Listener {
- NioPrintStream os;
+ LocalPipe os;
- SearchListener(NioPrintStream os) {
+ SearchListener(LocalPipe os) {
this.os = os;
}
public void notifyDepth(int depth) {
- os.printf("info depth %d%n", depth);
+ os.printLine("info depth %d", depth);
}
public void notifyCurrMove(Move m, int moveNr) {
- os.printf("info currmove %s currmovenumber %d%n", moveToString(m), moveNr);
+ os.printLine("info currmove %s currmovenumber %d", moveToString(m), moveNr);
}
public void notifyPV(int depth, int score, int time, long nodes, int nps, boolean isMate,
@@ -103,16 +105,16 @@ public class DroidEngineControl {
} else if (lowerBound) {
bound = " lowerbound";
}
- os.printf("info depth %d score %s %d%s time %d nodes %d nps %d pv%s%n",
+ os.printLine("info depth %d score %s %d%s time %d nodes %d nps %d pv%s",
depth, isMate ? "mate" : "cp", score, bound, time, nodes, nps, pvBuf.toString());
}
public void notifyStats(long nodes, int nps, int time) {
- os.printf("info nodes %d nps %d time %d%n", nodes, nps, time);
+ os.printLine("info nodes %d nps %d time %d", nodes, nps, time);
}
}
- public DroidEngineControl(NioPrintStream os) {
+ public DroidEngineControl(LocalPipe os) {
this.os = os;
threadMutex = new Object();
setupTT();
@@ -260,9 +262,9 @@ public class DroidEngineControl {
Move ponderMove = getPonderMove(pos, m);
synchronized (threadMutex) {
if (ponderMove != null) {
- os.printf("bestmove %s ponder %s%n", moveToString(m), moveToString(ponderMove));
+ os.printLine("bestmove %s ponder %s", moveToString(m), moveToString(ponderMove));
} else {
- os.printf("bestmove %s%n", moveToString(m));
+ os.printLine("bestmove %s", moveToString(m));
}
engineThread = null;
sc = null;
@@ -362,14 +364,14 @@ public class DroidEngineControl {
return ret;
}
- static void printOptions(NioPrintStream os) {
- os.printf("option name Hash type spin default 2 min 1 max 2048%n");
- os.printf("option name OwnBook type check default false%n");
- os.printf("option name Ponder type check default true%n");
- os.printf("option name UCI_AnalyseMode type check default false%n");
- os.printf("option name UCI_EngineAbout type string default %s by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html%n",
+ static void printOptions(LocalPipe os) {
+ os.printLine("option name Hash type spin default 2 min 1 max 2048");
+ os.printLine("option name OwnBook type check default false");
+ os.printLine("option name Ponder type check default true");
+ os.printLine("option name UCI_AnalyseMode type check default false");
+ os.printLine("option name UCI_EngineAbout type string default %s by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html",
ComputerPlayer.engineName);
- os.printf("option name Strength type spin default 1000 min 0 max 1000\n");
+ os.printLine("option name Strength type spin default 1000 min 0 max 1000");
}
final void setOption(String optionName, String optionValue) {
diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioInputStream.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioInputStream.java
deleted file mode 100644
index 5bb60b8..0000000
--- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioInputStream.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- DroidFish - An Android chess program.
- Copyright (C) 2011 Peter Ă–sterlund, peterosterlund2@gmail.com
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-package org.petero.droidfish.engine.cuckoochess;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.Pipe;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.util.ArrayList;
-
-/** Simple InputStream look-alike on top of nio. */
-class NioInputStream {
- Pipe.SourceChannel in;
- ByteBuffer buffer;
- Selector selector;
-
- ArrayList inBuf;
- StringBuilder lineBuf;
-
- public NioInputStream(Pipe pipe) {
- in = pipe.source();
- try {
- in.configureBlocking(false);
- selector = Selector.open();
- in.register(selector, SelectionKey.OP_READ);
-
- buffer = ByteBuffer.allocate(1024);
- inBuf = new ArrayList();
- lineBuf = new StringBuilder(128);
- } catch (IOException e) {
- }
- }
-
- public String readLine() {
- while (true) {
- String s = readLine(1000);
- if (s != null)
- return s;
- }
- }
-
- public String readLine(int timeoutMillis) {
- try {
- boolean haveNewLine = false;
- for (int i = 0; i < inBuf.size(); i++) {
- if (inBuf.get(i) == '\n') {
- haveNewLine = true;
- break;
- }
- }
- if (!haveNewLine) {
- // Refill inBuf
- if (timeoutMillis < 1)
- timeoutMillis = 1;
- selector.select(timeoutMillis);
- buffer.clear();
- for (SelectionKey sk : selector.selectedKeys())
- if (sk.isValid() && sk.isReadable())
- in.read(buffer);
- buffer.flip();
- while (buffer.position() < buffer.limit()) {
- byte b = buffer.get();
- inBuf.add((char)b);
- }
- }
-
- // Extract line
- String ret = "";
- int i;
- for (i = 0; i < inBuf.size(); i++) {
- char c = inBuf.get(i);
- if (c == '\n') {
- int newSize = inBuf.size() - i - 1;
- for (int j = 0; j < newSize; j++)
- inBuf.set(j, inBuf.get(j+i+1));
- while (inBuf.size() > newSize)
- inBuf.remove(inBuf.size() - 1);
- ret = lineBuf.toString();
- lineBuf = new StringBuilder(128);
- break;
- } else {
- lineBuf.append(c);
- }
- }
- if (i == inBuf.size())
- inBuf.clear();
- return ret;
- } catch (IOException e) {
- }
- return null;
- }
-}
diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioPrintStream.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioPrintStream.java
deleted file mode 100644
index f367777..0000000
--- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/NioPrintStream.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- DroidFish - An Android chess program.
- Copyright (C) 2011 Peter Ă–sterlund, peterosterlund2@gmail.com
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-package org.petero.droidfish.engine.cuckoochess;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.Pipe;
-
-/** Simple PrintStream look-alike on top of nio. */
-class NioPrintStream {
- Pipe.SinkChannel out;
-
- public NioPrintStream(Pipe pipe) {
- out = pipe.sink();
- }
-
- public void printf(String format) {
- try {
- String s = String.format(format, new Object[]{});
- out.write(ByteBuffer.wrap(s.getBytes()));
- } catch (IOException e) {
- }
- }
-
- public void printf(String format, Object ... args) {
- try {
- String s = String.format(format, args);
- out.write(ByteBuffer.wrap(s.getBytes()));
- } catch (IOException e) {
- }
- }
-}