@Override public void deliverReply(Reply reply, ReplyHandler handler) { msn.deliverReply(reply, handler); }
/** * <p>Convenience method to post a {@link Task} that delivers a {@link * Reply} to a {@link ReplyHandler} to the queue of tasks to be * executed.</p> * * @param reply The reply to return. * @param handler The handler to return to. */ public void deliverReply(final Reply reply, final ReplyHandler handler) { enqueue(new ReplyTask(reply, handler)); }
/** * <p>Synchronize with internal threads. This method will handshake with all * internal threads. This has the implicit effect of waiting for all active * callbacks. Note that this method should never be invoked from a callback * since that would make the thread wait for itself... forever. This method * is typically used to untangle during session shutdown.</p> */ public void sync() { msn.sync(); net.sync(); }
msn = new Messenger(); msn.addRecurrentTask(new ResenderTask(resender)); } else { resender = null; careTaker.start(); msn.start();
@Override public void handleMessage(Message msg) { if (resender != null && msg.hasBucketSequence()) { deliverError(msg, ErrorCode.SEQUENCE_ERROR, "Bucket sequences not supported when resender is enabled."); return; } SendProxy proxy = new SendProxy(this, net, resender); msn.deliverMessage(msg, proxy); }
/** * <p>Sets the destroyed flag to true. The very first time this method is * called, it cleans up all its dependencies. Even if you retain a reference * to this object, all of its content is allowed to be garbage * collected.</p> * * @return True if content existed and was destroyed. */ public boolean destroy() { if (!destroyed.getAndSet(true)) { try { careTaker.join(); } catch (InterruptedException e) { } protocolRepository.clearPolicyCache(); net.shutdown(); msn.destroy(); if (resender != null) { resender.destroy(); } return true; } return false; }
@Override public void deliverMessage(Message msg, String session) { MessageHandler msgHandler = sessions.get(session); if (msgHandler == null) { deliverError(msg, ErrorCode.UNKNOWN_SESSION, "Session '" + session + "' does not exist."); } else if (!checkPending(msg)) { deliverError(msg, ErrorCode.SESSION_BUSY, "Session '" + net.getConnectionSpec() + "/" + session + "' is busy, try again later."); } else { msn.deliverMessage(msg, msgHandler); } }
/** * <p>Handshakes with the internal thread. If this method is called using * the messenger thread, this will deadlock.</p> */ public void sync() { if (Thread.currentThread() == thread) { return; // no need to wait for self } final SyncTask task = new SyncTask(); enqueue(task); task.await(); }
/** * <p>Sets the destroyed flag to true. The very first time this method is * called, it cleans up all its dependencies. Even if you retain a * reference to this object, all of its content is allowed to be garbage * collected.</p> * * @return True if content existed and was destroyed. */ public boolean destroy() { boolean done = false; enqueue(Terminate.INSTANCE); if (!destroyed.getAndSet(true)) { sendExecutor.shutdownNow().forEach((Runnable task) -> {((MessageTask) task).msg.discard();}); try { synchronized (this) { while (!queue.isEmpty()) { wait(); } } thread.join(); } catch (final InterruptedException e) { // ignore } done = true; } return done; }