public void close() { Thread t = null; // This code avoids deadlock of calling close() from different threads // and avoid multiple closes synchronized (access) { if (worker != null) { t = worker; worker = null; } } // Then, releasing the lock, we perform closing, only once: if (t != null) { requestStop = true; t.interrupt(); // While the worker closes, we can free up the queue: EOFException eof = new EOFException(); // synchronized (resultQueue) { for (CommandResult dr : resultQueue.values()) { dr.sendFailure(eof); } resultQueue.clear(); // } // try { // t.join(); // } catch (InterruptedException ignored) { // } connector.close(); } }
private void receiveCommands() { while (!requestStop) { try { Map<String, Object> input = connector.receive(); if (input == null) break; int serial = ((Number) input.get("serial")).intValue(); if (inSerial++ != serial) throw new ProtocolException("farcall sync lost"); Number ref = (Number) input.get("ref"); if (ref != null) { processReply(input, ref.intValue()); } else { processCommand(input, serial); } } catch (EOFException e) { log.i("closing farcall instance on eof encountered"); close(); } catch (IOException e) { log.wtf("internal error", e); break; } } close(); }
private CommandResult sendToRemote(Object... keysValues) { HashMap<String, Object> packet = Ut.mapFromArray(keysValues); synchronized (access) { if (isClosed()) { CommandResult closedResult = new CommandResult(0); closedResult.sendFailure(new EOFException("farcall is closed")); return closedResult; } packet.put("serial", outSerial); CommandResult result = new CommandResult(outSerial); // synchronized (resultQueue) { resultQueue.put(outSerial, result); // } try { connector.send(packet); } catch (IOException e) { // synchronized (resultQueue) { resultQueue.remove(outSerial); // } result.sendFailure(e); close(); return result; } outSerial++; return result; } }