package cz.cuni.mff.d3s.been.mq; import org.jeromq.ZMQ; import org.jeromq.ZMQ.Poller; import org.jeromq.ZMQ.Socket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A singleton provider for {@link ZMQContext} instances. * * @author Martin Sixta * @author darklight */ public final class Context implements ZMQContext { private static final Logger log = LoggerFactory.getLogger(Context.class); // STATIC FIELDS /** Actual static {@link org.jeromq.ZMQ.Context} */ private static ZMQ.Context zctx = null; /** Number of references provided */ private static int refCount = 0; /** Number of I/O threads 0MQ uses */ private static final int ZMQ_IO_THREADS = 1; // INSTANCE FIELDS /** * Whether this {@link ZMQContext} is still valid (i.e. hasn't been released * yet) */ private boolean valid = true; /** * Deny instantiation, we only want to have this object created via * {@link #getReference()}. */ private Context() {} @Override public synchronized void term() throws MessagingException { checkValid(); valid = false; releaseContext(); } @Override public Socket socket(int type) throws MessagingException { checkValid(); return zctx.socket(type); } @Override public Poller poller() throws MessagingException { checkValid(); return zctx.poller(); } @Override public Poller poller(int size) throws MessagingException { checkValid(); return zctx.poller(size); } private void checkValid() throws MessagingException { if (!valid) { throw new MessagingException("Invoked operation on released context."); } } /** * Get a counted reference to the 0MQ context * * @return The reference */ public synchronized static ZMQContext getReference() { if (zctx == null) { zctx = ZMQ.context(ZMQ_IO_THREADS); } ++refCount; return new Context(); } private static synchronized void releaseContext() { if (refCount == 0) { throw new IllegalStateException("No context to be released"); } --refCount; if (refCount == 0) { try { zctx.term(); } catch (RuntimeException e) { log.warn("0MQ context termination failed due to underlying runtime exception", e); } zctx = null; } } }