From 1afab8c1f2c417b08371bc12569e03171851d785 Mon Sep 17 00:00:00 2001 From: Peter Ballard Date: Tue, 7 Jul 2015 13:33:47 +0100 Subject: Add option to only read from TCP socket when previous read has been processed By default this option is disabled, existing usages will function as normal. This option stops the JavaConnection from reading data if the previous read has not been processed by the event loop. Previously constrained devices were seeing OutOfMemoryErrors, if they were not able to process the incoming data quick enough. This change does not affect the write behavour. Change-Id: I47bc0eafba32336f5bf250ccb1fea530f51d328e diff --git a/src/com/isode/stroke/network/JavaConnection.java b/src/com/isode/stroke/network/JavaConnection.java index 3560e83..4e7503b 100644 --- a/src/com/isode/stroke/network/JavaConnection.java +++ b/src/com/isode/stroke/network/JavaConnection.java @@ -79,7 +79,8 @@ public class JavaConnection extends Connection implements EventOwner { while (!disconnecting_ || isWriteNeeded()) { /* Something(s) happened. See what needs doing */ boolean writeNeeded = isWriteNeeded(); - boolean readNeeded = selectionKey_.isReadable(); + boolean readNeeded = (selectionKey_.interestOps() & SelectionKey.OP_READ) != 0 + && selectionKey_.isReadable(); { /* Handle any writing */ if (writeNeeded) { @@ -299,21 +300,46 @@ public class JavaConnection extends Connection implements EventOwner { } private void handleDataRead(final ByteArray data) { + if (synchroniseReads_) { + selectionKey_.interestOps(0); + } eventLoop_.postEvent(new Callback() { public void run() { onDataRead.emit(data); + // Check "isOpen" to Avoid Android crash see + // https://code.google.com/p/android/issues/detail?id=80785 + if (synchroniseReads_ && selector_ != null) { + synchronized (selectorLock_) { + selectionKey_.interestOps(SelectionKey.OP_READ); + if (selector_.isOpen()) { + selector_.wakeup(); + } + } + } } }); } } - private JavaConnection(EventLoop eventLoop) { + private JavaConnection(EventLoop eventLoop, boolean synchroniseReads) { eventLoop_ = eventLoop; + synchroniseReads_ = synchroniseReads; } public static JavaConnection create(EventLoop eventLoop) { - return new JavaConnection(eventLoop); + return new JavaConnection(eventLoop, false); + } + + /** + * Creates a new JavaConnection + * @param eventLoop the EventLoop for read and write events to be posted to + * @param synchroniseReads if true then data will not be read from the connection + * until the previous read has been processed by the EventLoop + * @return a new JavaConnection + */ + public static JavaConnection create(EventLoop eventLoop, boolean synchroniseReads) { + return new JavaConnection(eventLoop, synchroniseReads); } @Override @@ -386,5 +412,6 @@ public class JavaConnection extends Connection implements EventOwner { private Selector selector_; private final Object selectorLock_ = new Object(); // use private lock object that is not visible elsewhere private Worker worker_; + private final boolean synchroniseReads_; } -- cgit v0.10.2-6-g49f6