package org.zeromq; import java.io.Closeable; import java.util.List; import java.util.ListIterator; import java.util.concurrent.CopyOnWriteArrayList; import org.zeromq.ZMQ.Context; import org.zeromq.ZMQ.Socket; /** * ZContext provides a high-level ZeroMQ context management class * * The ZContext class wraps java org.zeromq.Context objects, which in turn wrap native 0MQ contexts. It manages open * sockets in the context and automatically closes these before terminating the context. It provides a simple way to set * the linger timeout on sockets, and configure contexts for number of I/O threads. Sets-up signal (interrupt) handling * for the process. * * @see <a href="http://github.com/zeromq/czmq/blob/master/src/zctx.c">czmq version</a> * * @author rsmith (at) rsbatechnology (dot) co (dot) uk */ public class ZContext implements Closeable { /** * Reference to underlying Context object */ private ZMQ.Context context; /** * List of sockets managed by this ZContext */ private List<Socket> sockets; /** * Number of io threads allocated to this context, default 1 */ private int ioThreads; /** * Linger timeout, default 0 */ private int linger; /** * Indicates if context object is owned by main thread (useful for multi-threaded applications) */ private boolean main; /** * Class Constructor */ public ZContext() { context = null; // Don't create Context until create 1st 0MQ socket sockets = new CopyOnWriteArrayList<Socket>(); ioThreads = 1; linger = 0; main = true; } /** * Destructor. Call this to gracefully terminate context and close any managed 0MQ sockets */ public void destroy() { ListIterator<Socket> itr = sockets.listIterator(); while (itr.hasNext()) { destroySocket(itr.next()); } sockets.clear(); // Only terminate context if we are on the main thread if (isMain() && context != null) context.term(); } /** * Creates a new managed socket within this ZContext instance. Use this to get automatic management of the socket at * shutdown * * @param type socket type (see ZMQ static class members) * @return Newly created Socket object */ public Socket createSocket(int type) { if (context == null) context = ZMQ.context(ioThreads); // Create and register socket Socket socket = context.socket(type); sockets.add(socket); return socket; } /** * Destroys managed socket within this context and remove from sockets list * * @param s org.zeromq.Socket object to destroy */ public void destroySocket(Socket s) { if (s == null) return; if (sockets.contains(s)) { try { s.setLinger(linger); } catch (ZMQException e) { if (e.getErrorCode() != ZMQ.ETERM()) { throw e; } } s.close(); sockets.remove(s); } } /** * Creates new shadow context. Shares same underlying org.zeromq.Context instance but has own list of managed * sockets, io thread count etc. * * @param ctx Original ZContext to create shadow of * @return New ZContext */ public static ZContext shadow(ZContext ctx) { ZContext shadow = new ZContext(); shadow.setContext(ctx.getContext()); shadow.setMain(false); return shadow; } /** * @return the ioThreads */ public int getIoThreads() { return ioThreads; } /** * @param ioThreads the ioThreads to set */ public void setIoThreads(int ioThreads) { this.ioThreads = ioThreads; } /** * @return the linger */ public int getLinger() { return linger; } /** * @param linger the linger to set */ public void setLinger(int linger) { this.linger = linger; } /** * @return the main */ public boolean isMain() { return main; } /** * @param main the main to set */ public void setMain(boolean main) { this.main = main; } /** * @return the context */ public Context getContext() { return context; } /** * @param ctx sets the underlying org.zeromq.Context associated with this ZContext wrapper object */ public void setContext(Context ctx) { this.context = ctx; } /** * @return the sockets */ public List<Socket> getSockets() { return sockets; } @Override public void close() { destroy(); } }