PageRenderTime 108ms CodeModel.GetById 38ms RepoModel.GetById 22ms app.codeStats 0ms

/src/org/zeromq/ZMQ.java

https://github.com/thijsterlouw/jzmq
Java | 1043 lines | 351 code | 116 blank | 576 comment | 28 complexity | 42b0bcca4c50e54d688b74095f8fe2dd MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014
  1. /*
  2. Copyright (c) 2007-2010 iMatix Corporation
  3. This file is part of 0MQ.
  4. 0MQ is free software; you can redistribute it and/or modify it under
  5. the terms of the Lesser GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. 0MQ is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. Lesser GNU General Public License for more details.
  12. You should have received a copy of the Lesser GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package org.zeromq;
  16. import java.util.LinkedList;
  17. /**
  18. * ZeroMQ JNI Bindings.
  19. *
  20. * @author Gonzalo Diethelm
  21. *
  22. */
  23. public class ZMQ {
  24. static {
  25. System.loadLibrary ("jzmq");
  26. }
  27. // Values for flags in Socket's send and recv functions.
  28. /**
  29. * Socket flag to indicate a nonblocking send or recv mode.
  30. */
  31. public static final int NOBLOCK = 1;
  32. /**
  33. * Socket flag to indicate that more message parts are coming.
  34. */
  35. public static final int SNDMORE = 2;
  36. // Socket types, used when creating a Socket.
  37. /**
  38. * Flag to specify a exclusive pair of sockets.
  39. */
  40. public static final int PAIR = 0;
  41. /**
  42. * Flag to specify a PUB socket, receiving side must be a SUB.
  43. */
  44. public static final int PUB = 1;
  45. /**
  46. * Flag to specify the receiving part of the PUB socket.
  47. */
  48. public static final int SUB = 2;
  49. /**
  50. * Flag to specify a REQ socket, receiving side must be a REP.
  51. */
  52. public static final int REQ = 3;
  53. /**
  54. * Flag to specify the receiving part of a REQ socket.
  55. */
  56. public static final int REP = 4;
  57. /**
  58. * Flag to specify a XREQ socket, receiving side must be a XREP.
  59. */
  60. public static final int XREQ = 5;
  61. /**
  62. * Flag to specify the receiving part of a XREQ socket.
  63. */
  64. public static final int XREP = 6;
  65. /**
  66. * Flag to specify the receiving part of a PUSH socket.
  67. */
  68. public static final int PULL = 7;
  69. /**
  70. * Flag to specify a PUSH socket, receiving side must be a PULL.
  71. */
  72. public static final int PUSH = 8;
  73. /**
  74. * Flag to specify a STREAMER device.
  75. */
  76. public static final int STREAMER = 1;
  77. /**
  78. * Flag to specify a FORWARDER device.
  79. */
  80. public static final int FORWARDER = 2;
  81. /**
  82. * Flag to specify a QUEUE device.
  83. */
  84. public static final int QUEUE = 3;
  85. /**
  86. * @see ZMQ#PULL
  87. */
  88. @Deprecated
  89. public static final int UPSTREAM = PULL;
  90. /**
  91. * @see ZMQ#PUSH
  92. */
  93. @Deprecated
  94. public static final int DOWNSTREAM = PUSH;
  95. protected static native int version_full();
  96. protected static native int version_major();
  97. protected static native int version_minor();
  98. protected static native int version_patch();
  99. protected static native int make_version(int major, int minor, int patch);
  100. protected static native long ENOTSUP();
  101. protected static native long EPROTONOSUPPORT();
  102. protected static native long ENOBUFS();
  103. protected static native long ENETDOWN();
  104. protected static native long EADDRINUSE();
  105. protected static native long EADDRNOTAVAIL();
  106. protected static native long ECONNREFUSED();
  107. protected static native long EINPROGRESS();
  108. protected static native long EMTHREAD();
  109. protected static native long EFSM();
  110. protected static native long ENOCOMPATPROTO();
  111. protected static native long ETERM();
  112. /**
  113. * Inner class: Error.
  114. */
  115. public enum Error {
  116. ENOTSUP(ENOTSUP()),
  117. EPROTONOSUPPORT(EPROTONOSUPPORT()),
  118. ENOBUFS(ENOBUFS()),
  119. ENETDOWN(ENETDOWN()),
  120. EADDRINUSE(EADDRINUSE()),
  121. EADDRNOTAVAIL(EADDRNOTAVAIL()),
  122. ECONNREFUSED(ECONNREFUSED()),
  123. EINPROGRESS(EINPROGRESS()),
  124. EMTHREAD(EMTHREAD()),
  125. EFSM(EFSM()),
  126. ENOCOMPATPROTO(ENOCOMPATPROTO()),
  127. ETERM(ETERM());
  128. private final long code;
  129. Error(long code) {
  130. this.code = code;
  131. }
  132. public long getCode() {
  133. return code;
  134. }
  135. public static Error findByCode(int code) {
  136. for (Error e : Error.class.getEnumConstants()) {
  137. if (e.getCode() == code) {
  138. return e;
  139. }
  140. }
  141. throw new IllegalArgumentException("Unknown " + Error.class.getName() + " enum code:" + code);
  142. }
  143. }
  144. /**
  145. * Create a new Context.
  146. *
  147. * @param ioThreads
  148. * Number of threads to use, usually 1 is sufficient for most use cases.
  149. * @return the Context
  150. */
  151. public static Context context (int ioThreads) {
  152. return new Context (ioThreads);
  153. }
  154. /**
  155. * Inner class: Context.
  156. */
  157. public static class Context {
  158. /**
  159. * This is an explicit "destructor". It can be called to ensure the corresponding 0MQ
  160. * Context has been disposed of.
  161. */
  162. public void term () {
  163. finalize ();
  164. }
  165. /**
  166. * Create a new Socket within this context.
  167. *
  168. * @param type
  169. * the socket type.
  170. * @return the newly created Socket.
  171. */
  172. public Socket socket (int type) {
  173. return new Socket (this, type);
  174. }
  175. /**
  176. * Create a new Poller within this context, with a default size.
  177. *
  178. * @return the newly created Poller.
  179. */
  180. public Poller poller () {
  181. return new Poller (this);
  182. }
  183. /**
  184. * Create a new Poller within this context, with a specified initial size.
  185. *
  186. * @param size
  187. * the poller initial size.
  188. * @return the newly created Poller.
  189. */
  190. public Poller poller (int size) {
  191. return new Poller (this, size);
  192. }
  193. /**
  194. * Class constructor.
  195. *
  196. * @param ioThreads
  197. * size of the threads pool to handle I/O operations.
  198. */
  199. protected Context (int ioThreads) {
  200. construct (ioThreads);
  201. }
  202. /** Initialize the JNI interface */
  203. protected native void construct (int ioThreads);
  204. /** Free all resources used by JNI interface. */
  205. @Override
  206. protected native void finalize ();
  207. /**
  208. * Get the underlying context handle. This is private because it is only accessed from JNI,
  209. * where Java access controls are ignored.
  210. *
  211. * @return the internal 0MQ context handle.
  212. */
  213. private long getContextHandle () {
  214. return this.contextHandle;
  215. }
  216. /** Opaque data used by JNI driver. */
  217. private long contextHandle;
  218. }
  219. /**
  220. * Inner class: Socket.
  221. */
  222. public static class Socket {
  223. /**
  224. * This is an explicit "destructor". It can be called to ensure the corresponding 0MQ Socket
  225. * has been disposed of.
  226. */
  227. public void close () {
  228. finalize ();
  229. }
  230. /**
  231. * The 'ZMQ_TYPE option shall retrieve the socket type for the specified
  232. * 'socket'. The socket type is specified at socket creation time and
  233. * cannot be modified afterwards.
  234. *
  235. * @return the socket type.
  236. * @since 2.1.0
  237. */
  238. public long getType () {
  239. if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
  240. return -1;
  241. return getLongSockopt (TYPE);
  242. }
  243. /**
  244. * @see #setLinger(long)
  245. *
  246. * @return the linger period.
  247. * @since 2.1.0
  248. */
  249. public long getLinger () {
  250. if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
  251. return -1;
  252. return getLongSockopt (LINGER);
  253. }
  254. /**
  255. * @see #setHWM(long)
  256. *
  257. * @return the High Water Mark.
  258. */
  259. public long getHWM () {
  260. return getLongSockopt (HWM);
  261. }
  262. /**
  263. * @see #setSwap(long)
  264. *
  265. * @return the number of messages to swap at most.
  266. */
  267. public long getSwap () {
  268. return getLongSockopt (SWAP);
  269. }
  270. /**
  271. * @see #setAffinity(long)
  272. *
  273. * @return the affinity.
  274. */
  275. public long getAffinity () {
  276. return getLongSockopt (AFFINITY);
  277. }
  278. /**
  279. * @see #setIdentity(byte[])
  280. *
  281. * @return the Identitiy.
  282. */
  283. public byte [] getIdentity () {
  284. return getBytesSockopt (IDENTITY);
  285. }
  286. /**
  287. * @see #setRate(long)
  288. *
  289. * @return the Rate.
  290. */
  291. public long getRate () {
  292. return getLongSockopt (RATE);
  293. }
  294. /**
  295. * @see #setRecoveryInterval(long)
  296. *
  297. * @return the RecoveryIntervall.
  298. */
  299. public long getRecoveryInterval () {
  300. return getLongSockopt (RECOVERY_IVL);
  301. }
  302. /**
  303. * @see #setMulticastLoop(boolean)
  304. *
  305. * @return the Multicast Loop.
  306. */
  307. public boolean hasMulticastLoop () {
  308. return getLongSockopt (MCAST_LOOP) != 0;
  309. }
  310. /**
  311. * @see #setSendBufferSize(long)
  312. *
  313. * @return the kernel send buffer size.
  314. */
  315. public long getSendBufferSize () {
  316. return getLongSockopt (SNDBUF);
  317. }
  318. /**
  319. * @see #setReceiveBufferSize(long)
  320. *
  321. * @return the kernel receive buffer size.
  322. */
  323. public long getReceiveBufferSize () {
  324. return getLongSockopt (RCVBUF);
  325. }
  326. /**
  327. * The 'ZMQ_RCVMORE' option shall return a boolean value indicating if the multi-part
  328. * message currently being read from the specified 'socket' has more message parts to
  329. * follow. If there are no message parts to follow or if the message currently being read is
  330. * not a multi-part message a value of zero shall be returned. Otherwise, a value of 1 shall
  331. * be returned.
  332. *
  333. * @return true if there are more messages to receive.
  334. */
  335. public boolean hasReceiveMore () {
  336. return getLongSockopt (RCVMORE) != 0;
  337. }
  338. /**
  339. * The 'ZMQ_FD' option shall retrieve file descriptor associated with the 0MQ
  340. * socket. The descriptor can be used to integrate 0MQ socket into an existing
  341. * event loop. It should never be used for anything else than polling -- such as
  342. * reading or writing. The descriptor signals edge-triggered IN event when
  343. * something has happened within the 0MQ socket. It does not necessarily mean that
  344. * the messages can be read or written. Check ZMQ_EVENTS option to find out whether
  345. * the 0MQ socket is readable or writeable.
  346. *
  347. * @return the underlying file descriptor.
  348. * @since 2.1.0
  349. */
  350. public long getFD () {
  351. if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
  352. return -1;
  353. return getLongSockopt (FD);
  354. }
  355. /**
  356. * The 'ZMQ_EVENTS' option shall retrieve event flags for the specified socket.
  357. * If a message can be read from the socket ZMQ_POLLIN flag is set. If message can
  358. * be written to the socket ZMQ_POLLOUT flag is set.
  359. *
  360. * @return the mask of outstanding events.
  361. * @since 2.1.0
  362. */
  363. public long getEvents () {
  364. if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
  365. return -1;
  366. return getLongSockopt (EVENTS);
  367. }
  368. /**
  369. * The 'ZMQ_LINGER' option shall retrieve the period for pending outbound
  370. * messages to linger in memory after closing the socket. Value of -1 means
  371. * infinite. Pending messages will be kept until they are fully transferred to
  372. * the peer. Value of 0 means that all the pending messages are dropped immediately
  373. * when socket is closed. Positive value means number of milliseconds to keep
  374. * trying to send the pending messages before discarding them.
  375. *
  376. * @param linger
  377. * the linger period.
  378. * @since 2.1.0
  379. */
  380. public void setLinger (long linger) {
  381. if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
  382. return;
  383. setLongSockopt (LINGER, linger);
  384. }
  385. /**
  386. * The 'ZMQ_HWM' option shall set the high water mark for the specified 'socket'. The high
  387. * water mark is a hard limit on the maximum number of outstanding messages 0MQ shall queue
  388. * in memory for any single peer that the specified 'socket' is communicating with.
  389. *
  390. * If this limit has been reached the socket shall enter an exceptional state and depending
  391. * on the socket type, 0MQ shall take appropriate action such as blocking or dropping sent
  392. * messages. Refer to the individual socket descriptions in the man page of zmq_socket[3] for
  393. * details on the exact action taken for each socket type.
  394. *
  395. * @param hwm
  396. * the number of messages to queue.
  397. */
  398. public void setHWM (long hwm) {
  399. setLongSockopt (HWM, hwm);
  400. }
  401. /**
  402. * Get the Swap. The 'ZMQ_SWAP' option shall set the disk offload (swap) size for the
  403. * specified 'socket'. A socket which has 'ZMQ_SWAP' set to a non-zero value may exceed its
  404. * high water mark; in this case outstanding messages shall be offloaded to storage on disk
  405. * rather than held in memory.
  406. *
  407. * @param swap
  408. * The value of 'ZMQ_SWAP' defines the maximum size of the swap space in bytes.
  409. */
  410. public void setSwap (long swap) {
  411. setLongSockopt (SWAP, swap);
  412. }
  413. /**
  414. * Get the Affinity. The 'ZMQ_AFFINITY' option shall set the I/O thread affinity for newly
  415. * created connections on the specified 'socket'.
  416. *
  417. * Affinity determines which threads from the 0MQ I/O thread pool associated with the
  418. * socket's _context_ shall handle newly created connections. A value of zero specifies no
  419. * affinity, meaning that work shall be distributed fairly among all 0MQ I/O threads in the
  420. * thread pool. For non-zero values, the lowest bit corresponds to thread 1, second lowest
  421. * bit to thread 2 and so on. For example, a value of 3 specifies that subsequent
  422. * connections on 'socket' shall be handled exclusively by I/O threads 1 and 2.
  423. *
  424. * See also in the man page of zmq_init[3] for details on allocating the number of I/O threads for a
  425. * specific _context_.
  426. *
  427. * @param affinity
  428. * the affinity.
  429. */
  430. public void setAffinity (long affinity) {
  431. setLongSockopt (AFFINITY, affinity);
  432. }
  433. /**
  434. * The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'. Socket
  435. * identity determines if existing 0MQ infastructure (_message queues_, _forwarding
  436. * devices_) shall be identified with a specific application and persist across multiple
  437. * runs of the application.
  438. *
  439. * If the socket has no identity, each run of an application is completely separate from
  440. * other runs. However, with identity set the socket shall re-use any existing 0MQ
  441. * infrastructure configured by the previous run(s). Thus the application may receive
  442. * messages that were sent in the meantime, _message queue_ limits shall be shared with
  443. * previous run(s) and so on.
  444. *
  445. * Identity should be at least one byte and at most 255 bytes long. Identities starting with
  446. * binary zero are reserved for use by 0MQ infrastructure.
  447. *
  448. * @param identity
  449. */
  450. public void setIdentity (byte [] identity) {
  451. setBytesSockopt (IDENTITY, identity);
  452. }
  453. /**
  454. * The 'ZMQ_SUBSCRIBE' option shall establish a new message filter on a 'ZMQ_SUB' socket.
  455. * Newly created 'ZMQ_SUB' sockets shall filter out all incoming messages, therefore you
  456. * should call this option to establish an initial message filter.
  457. *
  458. * An empty 'option_value' of length zero shall subscribe to all incoming messages. A
  459. * non-empty 'option_value' shall subscribe to all messages beginning with the specified
  460. * prefix. Mutiple filters may be attached to a single 'ZMQ_SUB' socket, in which case a
  461. * message shall be accepted if it matches at least one filter.
  462. *
  463. * @param topic
  464. */
  465. public void subscribe (byte [] topic) {
  466. setBytesSockopt (SUBSCRIBE, topic);
  467. }
  468. /**
  469. * The 'ZMQ_UNSUBSCRIBE' option shall remove an existing message filter on a 'ZMQ_SUB'
  470. * socket. The filter specified must match an existing filter previously established with
  471. * the 'ZMQ_SUBSCRIBE' option. If the socket has several instances of the same filter
  472. * attached the 'ZMQ_UNSUBSCRIBE' option shall remove only one instance, leaving the rest in
  473. * place and functional.
  474. *
  475. * @param topic
  476. */
  477. public void unsubscribe (byte [] topic) {
  478. setBytesSockopt (UNSUBSCRIBE, topic);
  479. }
  480. /**
  481. * The 'ZMQ_RATE' option shall set the maximum send or receive data rate for multicast
  482. * transports such as in the man page of zmq_pgm[7] using the specified 'socket'.
  483. *
  484. * @param rate
  485. */
  486. public void setRate (long rate) {
  487. setLongSockopt (RATE, rate);
  488. }
  489. /**
  490. * The 'ZMQ_RECOVERY_IVL' option shall set the recovery interval for multicast transports
  491. * using the specified 'socket'. The recovery interval determines the maximum time in
  492. * seconds that a receiver can be absent from a multicast group before unrecoverable data
  493. * loss will occur.
  494. *
  495. * CAUTION: Excersize care when setting large recovery intervals as the data needed for
  496. * recovery will be held in memory. For example, a 1 minute recovery interval at a data rate
  497. * of 1Gbps requires a 7GB in-memory buffer. {Purpose of this Method}
  498. *
  499. * @param recovery_ivl
  500. */
  501. public void setRecoveryInterval (long recovery_ivl) {
  502. setLongSockopt (RECOVERY_IVL, recovery_ivl);
  503. }
  504. /**
  505. * The 'ZMQ_MCAST_LOOP' option shall control whether data sent via multicast transports
  506. * using the specified 'socket' can also be received by the sending host via loopback. A
  507. * value of zero disables the loopback functionality, while the default value of 1 enables
  508. * the loopback functionality. Leaving multicast loopback enabled when it is not required
  509. * can have a negative impact on performance. Where possible, disable 'ZMQ_MCAST_LOOP' in
  510. * production environments.
  511. *
  512. * @param mcast_loop
  513. */
  514. public void setMulticastLoop (boolean mcast_loop) {
  515. setLongSockopt (MCAST_LOOP, mcast_loop ? 1 : 0);
  516. }
  517. /**
  518. * The 'ZMQ_SNDBUF' option shall set the underlying kernel transmit buffer size for the
  519. * 'socket' to the specified size in bytes. A value of zero means leave the OS default
  520. * unchanged. For details please refer to your operating system documentation for the
  521. * 'SO_SNDBUF' socket option.
  522. *
  523. * @param sndbuf
  524. */
  525. public void setSendBufferSize (long sndbuf) {
  526. setLongSockopt (SNDBUF, sndbuf);
  527. }
  528. /**
  529. * The 'ZMQ_RCVBUF' option shall set the underlying kernel receive buffer size for the
  530. * 'socket' to the specified size in bytes. A value of zero means leave the OS default
  531. * unchanged. For details refer to your operating system documentation for the 'SO_RCVBUF'
  532. * socket option.
  533. *
  534. * @param rcvbuf
  535. */
  536. public void setReceiveBufferSize (long rcvbuf) {
  537. setLongSockopt (RCVBUF, rcvbuf);
  538. }
  539. /**
  540. * Bind to network interface. Start listening for new connections.
  541. *
  542. * @param addr
  543. * the endpoint to bind to.
  544. */
  545. public native void bind (String addr);
  546. /**
  547. * Connect to remote application.
  548. *
  549. * @param addr
  550. * the endpoint to connect to.
  551. */
  552. public native void connect (String addr);
  553. /**
  554. * Send a message.
  555. *
  556. * @param msg
  557. * the message to send, as an array of bytes.
  558. * @param flags
  559. * the flags to apply to the send operation.
  560. * @return true if send was successful, false otherwise.
  561. */
  562. public native boolean send (byte [] msg, int flags);
  563. /**
  564. * Receive a message.
  565. *
  566. * @param flags
  567. * the flags to apply to the receive operation.
  568. * @return the message received, as an array of bytes; null on error.
  569. */
  570. public native byte [] recv (int flags);
  571. /**
  572. * Class constructor.
  573. *
  574. * @param context
  575. * a 0MQ context previously created.
  576. * @param type
  577. * the socket type.
  578. */
  579. protected Socket (Context context, int type) {
  580. // We keep a local handle to context so that
  581. // garbage collection won't be too greedy on it.
  582. this.context = context;
  583. construct (context, type);
  584. }
  585. /** Initialize the JNI interface */
  586. protected native void construct (Context ctx, int type);
  587. /** Free all resources used by JNI interface. */
  588. @Override
  589. protected native void finalize ();
  590. /**
  591. * Get the socket option value, as a long.
  592. *
  593. * @param option
  594. * ID of the option to set.
  595. * @return The socket option value (as a long).
  596. */
  597. protected native long getLongSockopt (int option);
  598. /**
  599. * Get the socket option value, as a byte array.
  600. *
  601. * @param option
  602. * ID of the option to set.
  603. * @return The socket option value (as a byte array).
  604. */
  605. protected native byte [] getBytesSockopt (int option);
  606. /**
  607. * Set the socket option value, given as a long.
  608. *
  609. * @param option
  610. * ID of the option to set.
  611. * @param optval
  612. * value (as a long) to set the option to.
  613. */
  614. protected native void setLongSockopt (int option, long optval);
  615. /**
  616. * Set the socket option value, given as a byte array.
  617. *
  618. * @param option
  619. * ID of the option to set.
  620. * @param optval
  621. * value (as a byte array) to set the option to.
  622. */
  623. protected native void setBytesSockopt (int option, byte [] optval);
  624. /**
  625. * Get the underlying socket handle. This is private because it is only accessed from JNI,
  626. * where Java access controls are ignored.
  627. *
  628. * @return the internal 0MQ socket handle.
  629. */
  630. private long getSocketHandle () {
  631. return this.socketHandle;
  632. }
  633. /** Opaque data used by JNI driver. */
  634. private long socketHandle;
  635. private Context context = null;
  636. // private Constants use the appropriate setter instead.
  637. private static final int HWM = 1;
  638. // public static final int LWM = 2; // No longer supported
  639. private static final int SWAP = 3;
  640. private static final int AFFINITY = 4;
  641. private static final int IDENTITY = 5;
  642. private static final int SUBSCRIBE = 6;
  643. private static final int UNSUBSCRIBE = 7;
  644. private static final int RATE = 8;
  645. private static final int RECOVERY_IVL = 9;
  646. private static final int MCAST_LOOP = 10;
  647. private static final int SNDBUF = 11;
  648. private static final int RCVBUF = 12;
  649. private static final int RCVMORE = 13;
  650. private static final int FD = 14;
  651. private static final int EVENTS = 15;
  652. private static final int TYPE = 16;
  653. private static final int LINGER = 17;
  654. }
  655. /**
  656. * Inner class: Poller.
  657. */
  658. public static class Poller {
  659. /**
  660. * These values can be ORed to specify what we want to poll for.
  661. */
  662. public static final int POLLIN = 1;
  663. public static final int POLLOUT = 2;
  664. public static final int POLLERR = 4;
  665. /**
  666. * Register a Socket for polling on all events.
  667. *
  668. * @param socket
  669. * the Socket we are registering.
  670. * @return the index identifying this Socket in the poll set.
  671. */
  672. public int register (Socket socket) {
  673. return register (socket, POLLIN | POLLOUT | POLLERR);
  674. }
  675. /**
  676. * Register a Socket for polling on the specified events.
  677. *
  678. * Automatically grow the internal representation if needed.
  679. *
  680. * @param socket
  681. * the Socket we are registering.
  682. * @param events
  683. * a mask composed by XORing POLLIN, POLLOUT and POLLERR.
  684. * @return the index identifying this Socket in the poll set.
  685. */
  686. public int register (Socket socket, int events) {
  687. int pos = -1;
  688. if (! this.freeSlots.isEmpty()) {
  689. // If there are free slots in our array, remove one
  690. // from the free list and use it.
  691. pos = this.freeSlots.remove();
  692. } else {
  693. if (this.next >= this.size) {
  694. // It is necessary to grow the arrays.
  695. // Compute new size for internal arrays.
  696. int nsize = this.size + SIZE_INCREMENT;
  697. // Create new internal arrays.
  698. Socket [] ns = new Socket [nsize];
  699. short [] ne = new short [nsize];
  700. short [] nr = new short [nsize];
  701. // Copy contents of current arrays into new arrays.
  702. for (int i = 0; i < this.next; ++i) {
  703. ns[i] = this.sockets[i];
  704. ne[i] = this.events[i];
  705. nr[i] = this.revents[i];
  706. }
  707. // Swap internal arrays and size to new values.
  708. this.size = nsize;
  709. this.sockets = ns;
  710. this.events = ne;
  711. this.revents = nr;
  712. }
  713. pos = this.next++;
  714. }
  715. this.sockets[pos] = socket;
  716. this.events[pos] = (short) events;
  717. this.used++;
  718. return pos;
  719. }
  720. /**
  721. * Unregister a Socket for polling on the specified events.
  722. *
  723. * @param socket
  724. * the Socket to be unregistered
  725. */
  726. public void unregister (Socket socket) {
  727. for (int i = 0; i < this.next; ++i) {
  728. if (this.sockets[i] == socket) {
  729. this.sockets[i] = null;
  730. this.events[i] = 0;
  731. this.revents[i] = 0;
  732. this.freeSlots.add(i);
  733. --this.used;
  734. break;
  735. }
  736. }
  737. }
  738. /**
  739. * Get the socket associated with an index.
  740. *
  741. * @param index
  742. * the desired index.
  743. * @return the Socket associated with that index (or null).
  744. */
  745. public Socket getSocket (int index) {
  746. if (index < 0 || index >= this.next)
  747. return null;
  748. return this.sockets [index];
  749. }
  750. /**
  751. * Get the current poll timeout.
  752. *
  753. * @return the current poll timeout in microseconds.
  754. * @deprecated Timeout handling has been moved to the poll() methods.
  755. */
  756. public long getTimeout () {
  757. return this.timeout;
  758. }
  759. /**
  760. * Set the poll timeout.
  761. *
  762. * @param timeout
  763. * the desired poll timeout in microseconds.
  764. * @deprecated Timeout handling has been moved to the poll() methods.
  765. */
  766. public void setTimeout (long timeout) {
  767. if (timeout < -1)
  768. return;
  769. this.timeout = timeout;
  770. }
  771. /**
  772. * Get the current poll set size.
  773. *
  774. * @return the current poll set size.
  775. */
  776. public int getSize () {
  777. return this.size;
  778. }
  779. /**
  780. * Get the index for the next position in the poll set size.
  781. *
  782. * @return the index for the next position in the poll set size.
  783. */
  784. public int getNext () {
  785. return this.next;
  786. }
  787. /**
  788. * Issue a poll call. If the poller's internal timeout value
  789. * has been set, use that value as timeout; otherwise, block
  790. * indefinitely.
  791. *
  792. * @return how many objects where signalled by poll ().
  793. */
  794. public long poll () {
  795. long tout = -1;
  796. if (this.timeout > -1) {
  797. tout = this.timeout;
  798. }
  799. return poll(tout);
  800. }
  801. /**
  802. * Issue a poll call, using the specified timeout value.
  803. *
  804. * @param tout
  805. * the timeout in microseconds, as per zmq_poll ();
  806. * if -1, it will block indefinitely until an event
  807. * happens; if 0, it will return immediately;
  808. * otherwise, it will wait for at most that many
  809. * microseconds.
  810. *
  811. * @return how many objects where signalled by poll ()
  812. */
  813. public long poll (long tout) {
  814. if (tout < -1) {
  815. return 0;
  816. }
  817. if (this.size <= 0 || this.next <= 0) {
  818. return 0;
  819. }
  820. for (int i = 0; i < this.next; ++i) {
  821. this.revents [i] = 0;
  822. }
  823. return run_poll (this.used, this.sockets, this.events, this.revents, tout);
  824. }
  825. /**
  826. * Check whether the specified element in the poll set was signalled for input.
  827. *
  828. * @param index
  829. *
  830. * @return true if the element was signalled.
  831. */
  832. public boolean pollin (int index) {
  833. return poll_mask (index, POLLIN);
  834. }
  835. /**
  836. * Check whether the specified element in the poll set was signalled for output.
  837. *
  838. * @param index
  839. *
  840. * @return true if the element was signalled.
  841. */
  842. public boolean pollout (int index) {
  843. return poll_mask (index, POLLOUT);
  844. }
  845. /**
  846. * Check whether the specified element in the poll set was signalled for error.
  847. *
  848. * @param index
  849. *
  850. * @return true if the element was signalled.
  851. */
  852. public boolean pollerr (int index) {
  853. return poll_mask (index, POLLERR);
  854. }
  855. /**
  856. * Class constructor.
  857. *
  858. * @param context
  859. * a 0MQ context previously created.
  860. */
  861. protected Poller (Context context) {
  862. this(context, SIZE_DEFAULT);
  863. }
  864. /**
  865. * Class constructor.
  866. *
  867. * @param context
  868. * a 0MQ context previously created.
  869. * @param size
  870. * the number of Sockets this poller will contain.
  871. */
  872. protected Poller (Context context, int size) {
  873. this.context = context;
  874. this.size = size;
  875. this.next = 0;
  876. this.sockets = new Socket [this.size];
  877. this.events = new short [this.size];
  878. this.revents = new short [this.size];
  879. freeSlots = new LinkedList<Integer>();
  880. }
  881. /**
  882. * Issue a poll call on the specified 0MQ sockets.
  883. *
  884. * @param sockets
  885. * an array of 0MQ Socket objects to poll.
  886. * @param events
  887. * an array of short values specifying what to poll for.
  888. * @param revents
  889. * an array of short values with the results.
  890. * @param timeout
  891. * the maximum timeout in microseconds.
  892. * @return how many objects where signalled by poll ().
  893. */
  894. private native long run_poll (int count, Socket [] sockets, short [] events, short [] revents, long timeout);
  895. /**
  896. * Check whether a specific mask was signalled by latest poll call.
  897. *
  898. * @param index
  899. * the index indicating the socket.
  900. * @param mask
  901. * a combination of POLLIN, POLLOUT and POLLERR.
  902. * @return true if specific socket was signalled as specified.
  903. */
  904. private boolean poll_mask (int index, int mask) {
  905. if (mask <= 0 || index < 0 || index >= this.next) {
  906. return false;
  907. }
  908. return (this.revents [index] & mask) > 0;
  909. }
  910. private Context context = null;
  911. private long timeout = -2; // mark as uninitialized
  912. private int size = 0;
  913. private int next = 0;
  914. private int used = 0;
  915. private Socket [] sockets = null;
  916. private short [] events = null;
  917. private short [] revents = null;
  918. // When socket is removed from polling, store free slots here
  919. private LinkedList<Integer> freeSlots = null;
  920. private static final int SIZE_DEFAULT = 32;
  921. private static final int SIZE_INCREMENT = 16;
  922. }
  923. }