rbczmq 1.6.2 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (398) hide show
  1. data/.gitignore +4 -3
  2. data/.gitmodules +6 -0
  3. data/.travis.yml +5 -1
  4. data/CHANGELOG.rdoc +15 -0
  5. data/Gemfile.lock +2 -2
  6. data/README.rdoc +5 -2
  7. data/Rakefile +8 -3
  8. data/ext/czmq/.gitignore +52 -0
  9. data/ext/czmq/.travis.yml +18 -0
  10. data/ext/czmq/AUTHORS +9 -0
  11. data/ext/czmq/COPYING +674 -0
  12. data/ext/czmq/COPYING.LESSER +178 -0
  13. data/ext/czmq/ChangeLog +0 -0
  14. data/ext/czmq/Makefile.am +22 -0
  15. data/ext/czmq/NEWS +263 -0
  16. data/ext/czmq/README +0 -0
  17. data/ext/czmq/README.md +1122 -0
  18. data/ext/czmq/README.txt +327 -0
  19. data/ext/czmq/autogen.sh +46 -0
  20. data/ext/czmq/builds/android/Android.mk +35 -0
  21. data/ext/czmq/builds/android/Application.mk +1 -0
  22. data/ext/czmq/builds/android/build.sh +59 -0
  23. data/ext/czmq/builds/android/clean.sh +26 -0
  24. data/ext/czmq/builds/mingw32/Makefile.mingw32 +38 -0
  25. data/ext/czmq/builds/mingw32/platform.h +0 -0
  26. data/ext/czmq/builds/msvc/.gitignore +18 -0
  27. data/ext/czmq/builds/msvc/README.txt +17 -0
  28. data/ext/czmq/builds/msvc/czmq.sln +69 -0
  29. data/ext/czmq/builds/msvc/czmq.vcproj +2246 -0
  30. data/ext/czmq/builds/msvc/czmq.vcxproj +329 -0
  31. data/ext/czmq/builds/msvc/czmq.vcxproj.filters +117 -0
  32. data/ext/czmq/builds/msvc/czmq11.sln +36 -0
  33. data/ext/czmq/builds/msvc/czmq_selftest.vcproj +840 -0
  34. data/ext/czmq/builds/msvc/czmq_selftest.vcxproj +189 -0
  35. data/ext/czmq/builds/msvc/czmq_selftest.vcxproj.filters +14 -0
  36. data/ext/czmq/c +520 -0
  37. data/ext/czmq/configure.ac +229 -0
  38. data/ext/czmq/doc/Makefile.am +49 -0
  39. data/ext/czmq/doc/asciidoc.conf +57 -0
  40. data/ext/czmq/doc/czmq.txt +334 -0
  41. data/ext/czmq/doc/mkman +100 -0
  42. data/ext/czmq/doc/mksite +65 -0
  43. data/ext/czmq/doc/wdput +43 -0
  44. data/ext/czmq/doc/xml2wd.pl +242 -0
  45. data/ext/czmq/doc/zbeacon.txt +173 -0
  46. data/ext/czmq/doc/zclock.txt +51 -0
  47. data/ext/czmq/doc/zconfig.txt +92 -0
  48. data/ext/czmq/doc/zctx.txt +111 -0
  49. data/ext/czmq/doc/zfile.txt +77 -0
  50. data/ext/czmq/doc/zframe.txt +222 -0
  51. data/ext/czmq/doc/zhash.txt +225 -0
  52. data/ext/czmq/doc/zlist.txt +176 -0
  53. data/ext/czmq/doc/zloop.txt +106 -0
  54. data/ext/czmq/doc/zmsg.txt +315 -0
  55. data/ext/czmq/doc/zmutex.txt +54 -0
  56. data/ext/czmq/doc/zsocket.txt +110 -0
  57. data/ext/czmq/doc/zsockopt.txt +528 -0
  58. data/ext/czmq/doc/zstr.txt +80 -0
  59. data/ext/czmq/doc/zsys.txt +44 -0
  60. data/ext/czmq/doc/zthread.txt +126 -0
  61. data/ext/czmq/doc/ztree.txt +236 -0
  62. data/ext/czmq/images/README_1.png +0 -0
  63. data/ext/czmq/images/README_2.png +0 -0
  64. data/ext/czmq/include/czmq.h +64 -0
  65. data/ext/czmq/include/czmq_prelude.h +504 -0
  66. data/ext/czmq/include/zbeacon.h +91 -0
  67. data/ext/czmq/include/zclock.h +56 -0
  68. data/ext/czmq/include/zconfig.h +117 -0
  69. data/ext/czmq/include/zctx.h +96 -0
  70. data/ext/czmq/include/zfile.h +82 -0
  71. data/ext/czmq/include/zframe.h +145 -0
  72. data/ext/czmq/include/zhash.h +127 -0
  73. data/ext/czmq/include/zlist.h +113 -0
  74. data/ext/czmq/include/zloop.h +98 -0
  75. data/ext/czmq/include/zmsg.h +165 -0
  76. data/ext/czmq/include/zmutex.h +62 -0
  77. data/ext/czmq/include/zsocket.h +104 -0
  78. data/ext/czmq/include/zsockopt.h +249 -0
  79. data/ext/czmq/include/zstr.h +69 -0
  80. data/ext/czmq/include/zsys.h +66 -0
  81. data/ext/czmq/include/zthread.h +62 -0
  82. data/ext/czmq/include/ztree.h +133 -0
  83. data/ext/czmq/mkdoc +14 -0
  84. data/ext/czmq/model/generate +2 -0
  85. data/ext/czmq/model/sockopts.xml +101 -0
  86. data/ext/czmq/notes.txt +21 -0
  87. data/ext/czmq/scripts/sockopts.gsl +325 -0
  88. data/ext/czmq/src/Makefile.am +61 -0
  89. data/ext/czmq/src/czmq_selftest.c +60 -0
  90. data/ext/czmq/src/libczmq.pc.in +11 -0
  91. data/ext/czmq/src/selftest +7 -0
  92. data/ext/czmq/src/selftest.cfg +5 -0
  93. data/ext/czmq/src/valgrind.supp +14 -0
  94. data/ext/czmq/src/vg +2 -0
  95. data/ext/czmq/src/zbeacon.c +787 -0
  96. data/ext/czmq/src/zclock.c +143 -0
  97. data/ext/czmq/src/zconfig.c +691 -0
  98. data/ext/czmq/src/zctx.c +287 -0
  99. data/ext/czmq/src/zfile.c +237 -0
  100. data/ext/czmq/src/zframe.c +551 -0
  101. data/ext/czmq/src/zhash.c +664 -0
  102. data/ext/czmq/src/zlist.c +459 -0
  103. data/ext/czmq/src/zloop.c +496 -0
  104. data/ext/czmq/src/zmsg.c +854 -0
  105. data/ext/czmq/src/zmutex.c +134 -0
  106. data/ext/czmq/src/zsocket.c +313 -0
  107. data/ext/czmq/src/zsockopt.c +1756 -0
  108. data/ext/czmq/src/zstr.c +297 -0
  109. data/ext/czmq/src/zsys.c +136 -0
  110. data/ext/czmq/src/zthread.c +269 -0
  111. data/ext/czmq/src/ztree.c +888 -0
  112. data/ext/czmq/version.sh +21 -0
  113. data/ext/rbczmq/extconf.rb +1 -18
  114. data/ext/rbczmq/poller.c +4 -1
  115. data/ext/rbczmq/socket.c +28 -5
  116. data/ext/rbczmq/socket.h +1 -0
  117. data/ext/zeromq/AUTHORS +110 -0
  118. data/ext/zeromq/CMakeLists.txt +392 -0
  119. data/ext/zeromq/COPYING +674 -0
  120. data/ext/zeromq/COPYING.LESSER +179 -0
  121. data/ext/zeromq/INSTALL +246 -0
  122. data/ext/zeromq/MAINTAINERS +56 -0
  123. data/ext/zeromq/Makefile.am +40 -0
  124. data/ext/zeromq/NEWS +333 -0
  125. data/ext/zeromq/README +39 -0
  126. data/ext/zeromq/acinclude.m4 +930 -0
  127. data/ext/zeromq/autogen.sh +45 -0
  128. data/ext/zeromq/branding.bmp +0 -0
  129. data/ext/zeromq/builds/msvc/Makefile.am +33 -0
  130. data/ext/zeromq/builds/msvc/c_local_lat/c_local_lat.vcproj +176 -0
  131. data/ext/zeromq/builds/msvc/c_local_lat/c_local_lat.vcxproj +87 -0
  132. data/ext/zeromq/builds/msvc/c_local_thr/c_local_thr.vcproj +176 -0
  133. data/ext/zeromq/builds/msvc/c_local_thr/c_local_thr.vcxproj +87 -0
  134. data/ext/zeromq/builds/msvc/c_remote_lat/c_remote_lat.vcproj +176 -0
  135. data/ext/zeromq/builds/msvc/c_remote_lat/c_remote_lat.vcxproj +87 -0
  136. data/ext/zeromq/builds/msvc/c_remote_thr/c_remote_thr.vcproj +176 -0
  137. data/ext/zeromq/builds/msvc/c_remote_thr/c_remote_thr.vcxproj +87 -0
  138. data/ext/zeromq/builds/msvc/errno.cpp +32 -0
  139. data/ext/zeromq/builds/msvc/errno.hpp +56 -0
  140. data/ext/zeromq/builds/msvc/inproc_lat/inproc_lat.vcproj +174 -0
  141. data/ext/zeromq/builds/msvc/inproc_lat/inproc_lat.vcxproj +86 -0
  142. data/ext/zeromq/builds/msvc/inproc_thr/inproc_thr.vcproj +174 -0
  143. data/ext/zeromq/builds/msvc/inproc_thr/inproc_thr.vcxproj +86 -0
  144. data/ext/zeromq/builds/msvc/libzmq/libzmq.vcproj +804 -0
  145. data/ext/zeromq/builds/msvc/libzmq/libzmq.vcxproj +252 -0
  146. data/ext/zeromq/builds/msvc/libzmq/libzmq.vcxproj.filters +431 -0
  147. data/ext/zeromq/builds/msvc/msvc.sln +89 -0
  148. data/ext/zeromq/builds/msvc/msvc10.sln +116 -0
  149. data/ext/zeromq/builds/msvc/platform.hpp +32 -0
  150. data/ext/zeromq/builds/msvc/properties/Common.props +21 -0
  151. data/ext/zeromq/builds/msvc/properties/Debug.props +19 -0
  152. data/ext/zeromq/builds/msvc/properties/Dynamic.props +20 -0
  153. data/ext/zeromq/builds/msvc/properties/Executable.props +19 -0
  154. data/ext/zeromq/builds/msvc/properties/Precompiled.props +14 -0
  155. data/ext/zeromq/builds/msvc/properties/Release.props +22 -0
  156. data/ext/zeromq/builds/msvc/properties/Win32.props +12 -0
  157. data/ext/zeromq/builds/msvc/properties/Win32_Release.props +17 -0
  158. data/ext/zeromq/builds/msvc/properties/WithOpenPGM.props +12 -0
  159. data/ext/zeromq/builds/msvc/properties/ZeroMQ.props +23 -0
  160. data/ext/zeromq/builds/msvc/properties/x64.props +12 -0
  161. data/ext/zeromq/builds/redhat/zeromq.spec.in +160 -0
  162. data/ext/zeromq/builds/valgrind/valgrind.supp +14 -0
  163. data/ext/zeromq/builds/valgrind/vg +1 -0
  164. data/ext/zeromq/cmake/Modules/TestZMQVersion.cmake +35 -0
  165. data/ext/zeromq/cmake/Modules/zmq_version.cpp +31 -0
  166. data/ext/zeromq/cmake/NSIS.template32.in +952 -0
  167. data/ext/zeromq/cmake/NSIS.template64.in +960 -0
  168. data/ext/zeromq/configure.in +428 -0
  169. data/ext/zeromq/doc/Makefile.am +51 -0
  170. data/ext/zeromq/doc/asciidoc.conf +56 -0
  171. data/ext/zeromq/doc/zmq.txt +233 -0
  172. data/ext/zeromq/doc/zmq_bind.txt +102 -0
  173. data/ext/zeromq/doc/zmq_close.txt +52 -0
  174. data/ext/zeromq/doc/zmq_connect.txt +98 -0
  175. data/ext/zeromq/doc/zmq_ctx_destroy.txt +66 -0
  176. data/ext/zeromq/doc/zmq_ctx_get.txt +67 -0
  177. data/ext/zeromq/doc/zmq_ctx_new.txt +49 -0
  178. data/ext/zeromq/doc/zmq_ctx_set.txt +75 -0
  179. data/ext/zeromq/doc/zmq_disconnect.txt +67 -0
  180. data/ext/zeromq/doc/zmq_epgm.txt +162 -0
  181. data/ext/zeromq/doc/zmq_errno.txt +50 -0
  182. data/ext/zeromq/doc/zmq_getsockopt.txt +516 -0
  183. data/ext/zeromq/doc/zmq_init.txt +52 -0
  184. data/ext/zeromq/doc/zmq_inproc.txt +85 -0
  185. data/ext/zeromq/doc/zmq_ipc.txt +85 -0
  186. data/ext/zeromq/doc/zmq_msg_close.txt +55 -0
  187. data/ext/zeromq/doc/zmq_msg_copy.txt +57 -0
  188. data/ext/zeromq/doc/zmq_msg_data.txt +48 -0
  189. data/ext/zeromq/doc/zmq_msg_get.txt +72 -0
  190. data/ext/zeromq/doc/zmq_msg_init.txt +65 -0
  191. data/ext/zeromq/doc/zmq_msg_init_data.txt +85 -0
  192. data/ext/zeromq/doc/zmq_msg_init_size.txt +58 -0
  193. data/ext/zeromq/doc/zmq_msg_more.txt +63 -0
  194. data/ext/zeromq/doc/zmq_msg_move.txt +52 -0
  195. data/ext/zeromq/doc/zmq_msg_recv.txt +125 -0
  196. data/ext/zeromq/doc/zmq_msg_send.txt +122 -0
  197. data/ext/zeromq/doc/zmq_msg_set.txt +45 -0
  198. data/ext/zeromq/doc/zmq_msg_size.txt +48 -0
  199. data/ext/zeromq/doc/zmq_pgm.txt +162 -0
  200. data/ext/zeromq/doc/zmq_poll.txt +132 -0
  201. data/ext/zeromq/doc/zmq_proxy.txt +97 -0
  202. data/ext/zeromq/doc/zmq_recv.txt +93 -0
  203. data/ext/zeromq/doc/zmq_recvmsg.txt +123 -0
  204. data/ext/zeromq/doc/zmq_send.txt +100 -0
  205. data/ext/zeromq/doc/zmq_sendmsg.txt +119 -0
  206. data/ext/zeromq/doc/zmq_setsockopt.txt +523 -0
  207. data/ext/zeromq/doc/zmq_socket.txt +369 -0
  208. data/ext/zeromq/doc/zmq_socket_monitor.txt +288 -0
  209. data/ext/zeromq/doc/zmq_strerror.txt +55 -0
  210. data/ext/zeromq/doc/zmq_tcp.txt +101 -0
  211. data/ext/zeromq/doc/zmq_term.txt +66 -0
  212. data/ext/zeromq/doc/zmq_unbind.txt +65 -0
  213. data/ext/zeromq/doc/zmq_version.txt +53 -0
  214. data/ext/zeromq/foreign/openpgm/Makefile.am +8 -0
  215. data/ext/zeromq/foreign/openpgm/libpgm-5.1.118~dfsg.tar.gz +0 -0
  216. data/ext/zeromq/include/zmq.h +402 -0
  217. data/ext/zeromq/include/zmq_utils.h +64 -0
  218. data/ext/zeromq/installer.ico +0 -0
  219. data/ext/zeromq/perf/Makefile.am +22 -0
  220. data/ext/zeromq/perf/inproc_lat.cpp +233 -0
  221. data/ext/zeromq/perf/inproc_thr.cpp +241 -0
  222. data/ext/zeromq/perf/local_lat.cpp +109 -0
  223. data/ext/zeromq/perf/local_thr.cpp +133 -0
  224. data/ext/zeromq/perf/remote_lat.cpp +122 -0
  225. data/ext/zeromq/perf/remote_thr.cpp +105 -0
  226. data/ext/zeromq/src/Makefile.am +171 -0
  227. data/ext/zeromq/src/address.cpp +78 -0
  228. data/ext/zeromq/src/address.hpp +52 -0
  229. data/ext/zeromq/src/array.hpp +155 -0
  230. data/ext/zeromq/src/atomic_counter.hpp +197 -0
  231. data/ext/zeromq/src/atomic_ptr.hpp +196 -0
  232. data/ext/zeromq/src/blob.hpp +129 -0
  233. data/ext/zeromq/src/clock.cpp +147 -0
  234. data/ext/zeromq/src/clock.hpp +60 -0
  235. data/ext/zeromq/src/command.hpp +154 -0
  236. data/ext/zeromq/src/config.hpp +89 -0
  237. data/ext/zeromq/src/ctx.cpp +352 -0
  238. data/ext/zeromq/src/ctx.hpp +173 -0
  239. data/ext/zeromq/src/dealer.cpp +133 -0
  240. data/ext/zeromq/src/dealer.hpp +92 -0
  241. data/ext/zeromq/src/decoder.cpp +166 -0
  242. data/ext/zeromq/src/decoder.hpp +248 -0
  243. data/ext/zeromq/src/devpoll.cpp +190 -0
  244. data/ext/zeromq/src/devpoll.hpp +105 -0
  245. data/ext/zeromq/src/dist.cpp +194 -0
  246. data/ext/zeromq/src/dist.hpp +105 -0
  247. data/ext/zeromq/src/encoder.cpp +102 -0
  248. data/ext/zeromq/src/encoder.hpp +200 -0
  249. data/ext/zeromq/src/epoll.cpp +178 -0
  250. data/ext/zeromq/src/epoll.hpp +101 -0
  251. data/ext/zeromq/src/err.cpp +291 -0
  252. data/ext/zeromq/src/err.hpp +155 -0
  253. data/ext/zeromq/src/fd.hpp +45 -0
  254. data/ext/zeromq/src/fq.cpp +141 -0
  255. data/ext/zeromq/src/fq.hpp +74 -0
  256. data/ext/zeromq/src/i_decoder.hpp +49 -0
  257. data/ext/zeromq/src/i_encoder.hpp +55 -0
  258. data/ext/zeromq/src/i_engine.hpp +55 -0
  259. data/ext/zeromq/src/i_msg_sink.hpp +43 -0
  260. data/ext/zeromq/src/i_msg_source.hpp +44 -0
  261. data/ext/zeromq/src/i_poll_events.hpp +47 -0
  262. data/ext/zeromq/src/io_object.cpp +108 -0
  263. data/ext/zeromq/src/io_object.hpp +81 -0
  264. data/ext/zeromq/src/io_thread.cpp +104 -0
  265. data/ext/zeromq/src/io_thread.hpp +91 -0
  266. data/ext/zeromq/src/ip.cpp +109 -0
  267. data/ext/zeromq/src/ip.hpp +41 -0
  268. data/ext/zeromq/src/ipc_address.cpp +84 -0
  269. data/ext/zeromq/src/ipc_address.hpp +67 -0
  270. data/ext/zeromq/src/ipc_connecter.cpp +265 -0
  271. data/ext/zeromq/src/ipc_connecter.hpp +128 -0
  272. data/ext/zeromq/src/ipc_listener.cpp +206 -0
  273. data/ext/zeromq/src/ipc_listener.hpp +99 -0
  274. data/ext/zeromq/src/kqueue.cpp +201 -0
  275. data/ext/zeromq/src/kqueue.hpp +107 -0
  276. data/ext/zeromq/src/lb.cpp +148 -0
  277. data/ext/zeromq/src/lb.hpp +73 -0
  278. data/ext/zeromq/src/libzmq.pc.in +10 -0
  279. data/ext/zeromq/src/likely.hpp +33 -0
  280. data/ext/zeromq/src/mailbox.cpp +87 -0
  281. data/ext/zeromq/src/mailbox.hpp +75 -0
  282. data/ext/zeromq/src/msg.cpp +299 -0
  283. data/ext/zeromq/src/msg.hpp +148 -0
  284. data/ext/zeromq/src/mtrie.cpp +428 -0
  285. data/ext/zeromq/src/mtrie.hpp +93 -0
  286. data/ext/zeromq/src/mutex.hpp +118 -0
  287. data/ext/zeromq/src/object.cpp +393 -0
  288. data/ext/zeromq/src/object.hpp +134 -0
  289. data/ext/zeromq/src/options.cpp +562 -0
  290. data/ext/zeromq/src/options.hpp +135 -0
  291. data/ext/zeromq/src/own.cpp +206 -0
  292. data/ext/zeromq/src/own.hpp +145 -0
  293. data/ext/zeromq/src/pair.cpp +136 -0
  294. data/ext/zeromq/src/pair.hpp +79 -0
  295. data/ext/zeromq/src/pgm_receiver.cpp +283 -0
  296. data/ext/zeromq/src/pgm_receiver.hpp +141 -0
  297. data/ext/zeromq/src/pgm_sender.cpp +218 -0
  298. data/ext/zeromq/src/pgm_sender.hpp +113 -0
  299. data/ext/zeromq/src/pgm_socket.cpp +706 -0
  300. data/ext/zeromq/src/pgm_socket.hpp +124 -0
  301. data/ext/zeromq/src/pipe.cpp +447 -0
  302. data/ext/zeromq/src/pipe.hpp +207 -0
  303. data/ext/zeromq/src/poll.cpp +176 -0
  304. data/ext/zeromq/src/poll.hpp +105 -0
  305. data/ext/zeromq/src/poller.hpp +82 -0
  306. data/ext/zeromq/src/poller_base.cpp +99 -0
  307. data/ext/zeromq/src/poller_base.hpp +86 -0
  308. data/ext/zeromq/src/precompiled.cpp +21 -0
  309. data/ext/zeromq/src/precompiled.hpp +47 -0
  310. data/ext/zeromq/src/proxy.cpp +150 -0
  311. data/ext/zeromq/src/proxy.hpp +32 -0
  312. data/ext/zeromq/src/pub.cpp +57 -0
  313. data/ext/zeromq/src/pub.hpp +69 -0
  314. data/ext/zeromq/src/pull.cpp +79 -0
  315. data/ext/zeromq/src/pull.hpp +81 -0
  316. data/ext/zeromq/src/push.cpp +76 -0
  317. data/ext/zeromq/src/push.hpp +80 -0
  318. data/ext/zeromq/src/random.cpp +52 -0
  319. data/ext/zeromq/src/random.hpp +37 -0
  320. data/ext/zeromq/src/reaper.cpp +117 -0
  321. data/ext/zeromq/src/reaper.hpp +80 -0
  322. data/ext/zeromq/src/rep.cpp +137 -0
  323. data/ext/zeromq/src/rep.hpp +80 -0
  324. data/ext/zeromq/src/req.cpp +185 -0
  325. data/ext/zeromq/src/req.hpp +91 -0
  326. data/ext/zeromq/src/router.cpp +364 -0
  327. data/ext/zeromq/src/router.hpp +138 -0
  328. data/ext/zeromq/src/select.cpp +216 -0
  329. data/ext/zeromq/src/select.hpp +126 -0
  330. data/ext/zeromq/src/session_base.cpp +503 -0
  331. data/ext/zeromq/src/session_base.hpp +156 -0
  332. data/ext/zeromq/src/signaler.cpp +406 -0
  333. data/ext/zeromq/src/signaler.hpp +63 -0
  334. data/ext/zeromq/src/socket_base.cpp +1236 -0
  335. data/ext/zeromq/src/socket_base.hpp +255 -0
  336. data/ext/zeromq/src/stdint.hpp +63 -0
  337. data/ext/zeromq/src/stream_engine.cpp +594 -0
  338. data/ext/zeromq/src/stream_engine.hpp +149 -0
  339. data/ext/zeromq/src/sub.cpp +93 -0
  340. data/ext/zeromq/src/sub.hpp +71 -0
  341. data/ext/zeromq/src/tcp.cpp +131 -0
  342. data/ext/zeromq/src/tcp.hpp +38 -0
  343. data/ext/zeromq/src/tcp_address.cpp +613 -0
  344. data/ext/zeromq/src/tcp_address.hpp +100 -0
  345. data/ext/zeromq/src/tcp_connecter.cpp +319 -0
  346. data/ext/zeromq/src/tcp_connecter.hpp +123 -0
  347. data/ext/zeromq/src/tcp_listener.cpp +293 -0
  348. data/ext/zeromq/src/tcp_listener.hpp +91 -0
  349. data/ext/zeromq/src/thread.cpp +107 -0
  350. data/ext/zeromq/src/thread.hpp +79 -0
  351. data/ext/zeromq/src/trie.cpp +337 -0
  352. data/ext/zeromq/src/trie.hpp +79 -0
  353. data/ext/zeromq/src/v1_decoder.cpp +162 -0
  354. data/ext/zeromq/src/v1_decoder.hpp +68 -0
  355. data/ext/zeromq/src/v1_encoder.cpp +103 -0
  356. data/ext/zeromq/src/v1_encoder.hpp +60 -0
  357. data/ext/zeromq/src/v1_protocol.hpp +43 -0
  358. data/ext/zeromq/src/version.rc.in +93 -0
  359. data/ext/zeromq/src/windows.hpp +181 -0
  360. data/ext/zeromq/src/wire.hpp +99 -0
  361. data/ext/zeromq/src/xpub.cpp +200 -0
  362. data/ext/zeromq/src/xpub.hpp +110 -0
  363. data/ext/zeromq/src/xsub.cpp +242 -0
  364. data/ext/zeromq/src/xsub.hpp +108 -0
  365. data/ext/zeromq/src/ypipe.hpp +210 -0
  366. data/ext/zeromq/src/yqueue.hpp +199 -0
  367. data/ext/zeromq/src/zmq.cpp +1058 -0
  368. data/ext/zeromq/src/zmq_utils.cpp +61 -0
  369. data/ext/zeromq/tests/Makefile.am +55 -0
  370. data/ext/zeromq/tests/test_connect_delay.cpp +260 -0
  371. data/ext/zeromq/tests/test_connect_resolve.cpp +54 -0
  372. data/ext/zeromq/tests/test_disconnect_inproc.cpp +120 -0
  373. data/ext/zeromq/tests/test_hwm.cpp +83 -0
  374. data/ext/zeromq/tests/test_invalid_rep.cpp +92 -0
  375. data/ext/zeromq/tests/test_last_endpoint.cpp +60 -0
  376. data/ext/zeromq/tests/test_monitor.cpp +289 -0
  377. data/ext/zeromq/tests/test_msg_flags.cpp +78 -0
  378. data/ext/zeromq/tests/test_pair_inproc.cpp +53 -0
  379. data/ext/zeromq/tests/test_pair_ipc.cpp +53 -0
  380. data/ext/zeromq/tests/test_pair_tcp.cpp +54 -0
  381. data/ext/zeromq/tests/test_reqrep_device.cpp +143 -0
  382. data/ext/zeromq/tests/test_reqrep_inproc.cpp +53 -0
  383. data/ext/zeromq/tests/test_reqrep_ipc.cpp +53 -0
  384. data/ext/zeromq/tests/test_reqrep_tcp.cpp +54 -0
  385. data/ext/zeromq/tests/test_router_mandatory.cpp +62 -0
  386. data/ext/zeromq/tests/test_shutdown_stress.cpp +93 -0
  387. data/ext/zeromq/tests/test_sub_forward.cpp +99 -0
  388. data/ext/zeromq/tests/test_term_endpoint.cpp +118 -0
  389. data/ext/zeromq/tests/test_timeo.cpp +119 -0
  390. data/ext/zeromq/tests/testutil.hpp +77 -0
  391. data/ext/zeromq/version.sh +21 -0
  392. data/lib/zmq/version.rb +1 -1
  393. data/rbczmq.gemspec +16 -3
  394. data/test/test_socket.rb +13 -1
  395. metadata +398 -9
  396. checksums.yaml +0 -15
  397. data/ext/czmq-1.4.1.tar.gz +0 -0
  398. data/ext/zeromq-3.2.3.tar.gz +0 -0
@@ -0,0 +1,210 @@
1
+ /*
2
+ Copyright (c) 2009-2011 250bpm s.r.o.
3
+ Copyright (c) 2007-2009 iMatix Corporation
4
+ Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
5
+
6
+ This file is part of 0MQ.
7
+
8
+ 0MQ is free software; you can redistribute it and/or modify it under
9
+ the terms of the GNU Lesser General Public License as published by
10
+ the Free Software Foundation; either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ 0MQ is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+
22
+ #ifndef __ZMQ_YPIPE_HPP_INCLUDED__
23
+ #define __ZMQ_YPIPE_HPP_INCLUDED__
24
+
25
+ #include "atomic_ptr.hpp"
26
+ #include "yqueue.hpp"
27
+ #include "platform.hpp"
28
+
29
+ namespace zmq
30
+ {
31
+
32
+ // Lock-free queue implementation.
33
+ // Only a single thread can read from the pipe at any specific moment.
34
+ // Only a single thread can write to the pipe at any specific moment.
35
+ // T is the type of the object in the queue.
36
+ // N is granularity of the pipe, i.e. how many items are needed to
37
+ // perform next memory allocation.
38
+
39
+ template <typename T, int N> class ypipe_t
40
+ {
41
+ public:
42
+
43
+ // Initialises the pipe.
44
+ inline ypipe_t ()
45
+ {
46
+ // Insert terminator element into the queue.
47
+ queue.push ();
48
+
49
+ // Let all the pointers to point to the terminator.
50
+ // (unless pipe is dead, in which case c is set to NULL).
51
+ r = w = f = &queue.back ();
52
+ c.set (&queue.back ());
53
+ }
54
+
55
+ // The destructor doesn't have to be virtual. It is mad virtual
56
+ // just to keep ICC and code checking tools from complaining.
57
+ inline virtual ~ypipe_t ()
58
+ {
59
+ }
60
+
61
+ // Following function (write) deliberately copies uninitialised data
62
+ // when used with zmq_msg. Initialising the VSM body for
63
+ // non-VSM messages won't be good for performance.
64
+
65
+ #ifdef ZMQ_HAVE_OPENVMS
66
+ #pragma message save
67
+ #pragma message disable(UNINIT)
68
+ #endif
69
+
70
+ // Write an item to the pipe. Don't flush it yet. If incomplete is
71
+ // set to true the item is assumed to be continued by items
72
+ // subsequently written to the pipe. Incomplete items are never
73
+ // flushed down the stream.
74
+ inline void write (const T &value_, bool incomplete_)
75
+ {
76
+ // Place the value to the queue, add new terminator element.
77
+ queue.back () = value_;
78
+ queue.push ();
79
+
80
+ // Move the "flush up to here" poiter.
81
+ if (!incomplete_)
82
+ f = &queue.back ();
83
+ }
84
+
85
+ #ifdef ZMQ_HAVE_OPENVMS
86
+ #pragma message restore
87
+ #endif
88
+
89
+ // Pop an incomplete item from the pipe. Returns true is such
90
+ // item exists, false otherwise.
91
+ inline bool unwrite (T *value_)
92
+ {
93
+ if (f == &queue.back ())
94
+ return false;
95
+ queue.unpush ();
96
+ *value_ = queue.back ();
97
+ return true;
98
+ }
99
+
100
+ // Flush all the completed items into the pipe. Returns false if
101
+ // the reader thread is sleeping. In that case, caller is obliged to
102
+ // wake the reader up before using the pipe again.
103
+ inline bool flush ()
104
+ {
105
+ // If there are no un-flushed items, do nothing.
106
+ if (w == f)
107
+ return true;
108
+
109
+ // Try to set 'c' to 'f'.
110
+ if (c.cas (w, f) != w) {
111
+
112
+ // Compare-and-swap was unseccessful because 'c' is NULL.
113
+ // This means that the reader is asleep. Therefore we don't
114
+ // care about thread-safeness and update c in non-atomic
115
+ // manner. We'll return false to let the caller know
116
+ // that reader is sleeping.
117
+ c.set (f);
118
+ w = f;
119
+ return false;
120
+ }
121
+
122
+ // Reader is alive. Nothing special to do now. Just move
123
+ // the 'first un-flushed item' pointer to 'f'.
124
+ w = f;
125
+ return true;
126
+ }
127
+
128
+ // Check whether item is available for reading.
129
+ inline bool check_read ()
130
+ {
131
+ // Was the value prefetched already? If so, return.
132
+ if (&queue.front () != r && r)
133
+ return true;
134
+
135
+ // There's no prefetched value, so let us prefetch more values.
136
+ // Prefetching is to simply retrieve the
137
+ // pointer from c in atomic fashion. If there are no
138
+ // items to prefetch, set c to NULL (using compare-and-swap).
139
+ r = c.cas (&queue.front (), NULL);
140
+
141
+ // If there are no elements prefetched, exit.
142
+ // During pipe's lifetime r should never be NULL, however,
143
+ // it can happen during pipe shutdown when items
144
+ // are being deallocated.
145
+ if (&queue.front () == r || !r)
146
+ return false;
147
+
148
+ // There was at least one value prefetched.
149
+ return true;
150
+ }
151
+
152
+ // Reads an item from the pipe. Returns false if there is no value.
153
+ // available.
154
+ inline bool read (T *value_)
155
+ {
156
+ // Try to prefetch a value.
157
+ if (!check_read ())
158
+ return false;
159
+
160
+ // There was at least one value prefetched.
161
+ // Return it to the caller.
162
+ *value_ = queue.front ();
163
+ queue.pop ();
164
+ return true;
165
+ }
166
+
167
+ // Applies the function fn to the first elemenent in the pipe
168
+ // and returns the value returned by the fn.
169
+ // The pipe mustn't be empty or the function crashes.
170
+ inline bool probe (bool (*fn)(T &))
171
+ {
172
+ bool rc = check_read ();
173
+ zmq_assert (rc);
174
+
175
+ return (*fn) (queue.front ());
176
+ }
177
+
178
+ protected:
179
+
180
+ // Allocation-efficient queue to store pipe items.
181
+ // Front of the queue points to the first prefetched item, back of
182
+ // the pipe points to last un-flushed item. Front is used only by
183
+ // reader thread, while back is used only by writer thread.
184
+ yqueue_t <T, N> queue;
185
+
186
+ // Points to the first un-flushed item. This variable is used
187
+ // exclusively by writer thread.
188
+ T *w;
189
+
190
+ // Points to the first un-prefetched item. This variable is used
191
+ // exclusively by reader thread.
192
+ T *r;
193
+
194
+ // Points to the first item to be flushed in the future.
195
+ T *f;
196
+
197
+ // The single point of contention between writer and reader thread.
198
+ // Points past the last flushed item. If it is NULL,
199
+ // reader is asleep. This pointer should be always accessed using
200
+ // atomic operations.
201
+ atomic_ptr_t <T> c;
202
+
203
+ // Disable copying of ypipe object.
204
+ ypipe_t (const ypipe_t&);
205
+ const ypipe_t &operator = (const ypipe_t&);
206
+ };
207
+
208
+ }
209
+
210
+ #endif
@@ -0,0 +1,199 @@
1
+ /*
2
+ Copyright (c) 2009-2011 250bpm s.r.o.
3
+ Copyright (c) 2007-2009 iMatix Corporation
4
+ Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
5
+
6
+ This file is part of 0MQ.
7
+
8
+ 0MQ is free software; you can redistribute it and/or modify it under
9
+ the terms of the GNU Lesser General Public License as published by
10
+ the Free Software Foundation; either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ 0MQ is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+
22
+ #ifndef __ZMQ_YQUEUE_HPP_INCLUDED__
23
+ #define __ZMQ_YQUEUE_HPP_INCLUDED__
24
+
25
+ #include <stdlib.h>
26
+ #include <stddef.h>
27
+
28
+ #include "err.hpp"
29
+ #include "atomic_ptr.hpp"
30
+
31
+ namespace zmq
32
+ {
33
+
34
+ // yqueue is an efficient queue implementation. The main goal is
35
+ // to minimise number of allocations/deallocations needed. Thus yqueue
36
+ // allocates/deallocates elements in batches of N.
37
+ //
38
+ // yqueue allows one thread to use push/back function and another one
39
+ // to use pop/front functions. However, user must ensure that there's no
40
+ // pop on the empty queue and that both threads don't access the same
41
+ // element in unsynchronised manner.
42
+ //
43
+ // T is the type of the object in the queue.
44
+ // N is granularity of the queue (how many pushes have to be done till
45
+ // actual memory allocation is required).
46
+
47
+ template <typename T, int N> class yqueue_t
48
+ {
49
+ public:
50
+
51
+ // Create the queue.
52
+ inline yqueue_t ()
53
+ {
54
+ begin_chunk = (chunk_t*) malloc (sizeof (chunk_t));
55
+ alloc_assert (begin_chunk);
56
+ begin_pos = 0;
57
+ back_chunk = NULL;
58
+ back_pos = 0;
59
+ end_chunk = begin_chunk;
60
+ end_pos = 0;
61
+ }
62
+
63
+ // Destroy the queue.
64
+ inline ~yqueue_t ()
65
+ {
66
+ while (true) {
67
+ if (begin_chunk == end_chunk) {
68
+ free (begin_chunk);
69
+ break;
70
+ }
71
+ chunk_t *o = begin_chunk;
72
+ begin_chunk = begin_chunk->next;
73
+ free (o);
74
+ }
75
+
76
+ chunk_t *sc = spare_chunk.xchg (NULL);
77
+ if (sc)
78
+ free (sc);
79
+ }
80
+
81
+ // Returns reference to the front element of the queue.
82
+ // If the queue is empty, behaviour is undefined.
83
+ inline T &front ()
84
+ {
85
+ return begin_chunk->values [begin_pos];
86
+ }
87
+
88
+ // Returns reference to the back element of the queue.
89
+ // If the queue is empty, behaviour is undefined.
90
+ inline T &back ()
91
+ {
92
+ return back_chunk->values [back_pos];
93
+ }
94
+
95
+ // Adds an element to the back end of the queue.
96
+ inline void push ()
97
+ {
98
+ back_chunk = end_chunk;
99
+ back_pos = end_pos;
100
+
101
+ if (++end_pos != N)
102
+ return;
103
+
104
+ chunk_t *sc = spare_chunk.xchg (NULL);
105
+ if (sc) {
106
+ end_chunk->next = sc;
107
+ sc->prev = end_chunk;
108
+ } else {
109
+ end_chunk->next = (chunk_t*) malloc (sizeof (chunk_t));
110
+ alloc_assert (end_chunk->next);
111
+ end_chunk->next->prev = end_chunk;
112
+ }
113
+ end_chunk = end_chunk->next;
114
+ end_pos = 0;
115
+ }
116
+
117
+ // Removes element from the back end of the queue. In other words
118
+ // it rollbacks last push to the queue. Take care: Caller is
119
+ // responsible for destroying the object being unpushed.
120
+ // The caller must also guarantee that the queue isn't empty when
121
+ // unpush is called. It cannot be done automatically as the read
122
+ // side of the queue can be managed by different, completely
123
+ // unsynchronised thread.
124
+ inline void unpush ()
125
+ {
126
+ // First, move 'back' one position backwards.
127
+ if (back_pos)
128
+ --back_pos;
129
+ else {
130
+ back_pos = N - 1;
131
+ back_chunk = back_chunk->prev;
132
+ }
133
+
134
+ // Now, move 'end' position backwards. Note that obsolete end chunk
135
+ // is not used as a spare chunk. The analysis shows that doing so
136
+ // would require free and atomic operation per chunk deallocated
137
+ // instead of a simple free.
138
+ if (end_pos)
139
+ --end_pos;
140
+ else {
141
+ end_pos = N - 1;
142
+ end_chunk = end_chunk->prev;
143
+ free (end_chunk->next);
144
+ end_chunk->next = NULL;
145
+ }
146
+ }
147
+
148
+ // Removes an element from the front end of the queue.
149
+ inline void pop ()
150
+ {
151
+ if (++ begin_pos == N) {
152
+ chunk_t *o = begin_chunk;
153
+ begin_chunk = begin_chunk->next;
154
+ begin_chunk->prev = NULL;
155
+ begin_pos = 0;
156
+
157
+ // 'o' has been more recently used than spare_chunk,
158
+ // so for cache reasons we'll get rid of the spare and
159
+ // use 'o' as the spare.
160
+ chunk_t *cs = spare_chunk.xchg (o);
161
+ if (cs)
162
+ free (cs);
163
+ }
164
+ }
165
+
166
+ private:
167
+
168
+ // Individual memory chunk to hold N elements.
169
+ struct chunk_t
170
+ {
171
+ T values [N];
172
+ chunk_t *prev;
173
+ chunk_t *next;
174
+ };
175
+
176
+ // Back position may point to invalid memory if the queue is empty,
177
+ // while begin & end positions are always valid. Begin position is
178
+ // accessed exclusively be queue reader (front/pop), while back and
179
+ // end positions are accessed exclusively by queue writer (back/push).
180
+ chunk_t *begin_chunk;
181
+ int begin_pos;
182
+ chunk_t *back_chunk;
183
+ int back_pos;
184
+ chunk_t *end_chunk;
185
+ int end_pos;
186
+
187
+ // People are likely to produce and consume at similar rates. In
188
+ // this scenario holding onto the most recently freed chunk saves
189
+ // us from having to call malloc/free.
190
+ atomic_ptr_t<chunk_t> spare_chunk;
191
+
192
+ // Disable copying of yqueue.
193
+ yqueue_t (const yqueue_t&);
194
+ const yqueue_t &operator = (const yqueue_t&);
195
+ };
196
+
197
+ }
198
+
199
+ #endif
@@ -0,0 +1,1058 @@
1
+ /*
2
+ Copyright (c) 2007-2012 iMatix Corporation
3
+ Copyright (c) 2009-2011 250bpm s.r.o.
4
+ Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
5
+
6
+ This file is part of 0MQ.
7
+
8
+ 0MQ is free software; you can redistribute it and/or modify it under
9
+ the terms of the GNU Lesser General Public License as published by
10
+ the Free Software Foundation; either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ 0MQ is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+ #define ZMQ_TYPE_UNSAFE
22
+
23
+ #include "platform.hpp"
24
+
25
+ #if defined ZMQ_FORCE_SELECT
26
+ #define ZMQ_POLL_BASED_ON_SELECT
27
+ #elif defined ZMQ_FORCE_POLL
28
+ #define ZMQ_POLL_BASED_ON_POLL
29
+ #elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\
30
+ defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\
31
+ defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\
32
+ defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\
33
+ defined ZMQ_HAVE_NETBSD
34
+ #define ZMQ_POLL_BASED_ON_POLL
35
+ #elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS ||\
36
+ defined ZMQ_HAVE_CYGWIN
37
+ #define ZMQ_POLL_BASED_ON_SELECT
38
+ #endif
39
+
40
+ // On AIX platform, poll.h has to be included first to get consistent
41
+ // definition of pollfd structure (AIX uses 'reqevents' and 'retnevents'
42
+ // instead of 'events' and 'revents' and defines macros to map from POSIX-y
43
+ // names to AIX-specific names).
44
+ #if defined ZMQ_POLL_BASED_ON_POLL
45
+ #include <poll.h>
46
+ #endif
47
+
48
+ // zmq.h must be included *after* poll.h for AIX to build properly
49
+ #include "../include/zmq.h"
50
+
51
+ #if defined ZMQ_HAVE_WINDOWS
52
+ #include "windows.hpp"
53
+ #else
54
+ #include <unistd.h>
55
+ #endif
56
+
57
+
58
+ // XSI vector I/O
59
+ #if ZMQ_HAVE_UIO
60
+ #include <sys/uio.h>
61
+ #else
62
+ struct iovec {
63
+ void *iov_base;
64
+ size_t iov_len;
65
+ };
66
+ #endif
67
+
68
+
69
+ #include <string.h>
70
+ #include <stdlib.h>
71
+ #include <new>
72
+
73
+ #include "proxy.hpp"
74
+ #include "socket_base.hpp"
75
+ #include "stdint.hpp"
76
+ #include "config.hpp"
77
+ #include "likely.hpp"
78
+ #include "clock.hpp"
79
+ #include "ctx.hpp"
80
+ #include "err.hpp"
81
+ #include "msg.hpp"
82
+ #include "fd.hpp"
83
+
84
+ #if !defined ZMQ_HAVE_WINDOWS
85
+ #include <unistd.h>
86
+ #endif
87
+
88
+ #if defined ZMQ_HAVE_OPENPGM
89
+ #define __PGM_WININT_H__
90
+ #include <pgm/pgm.h>
91
+ #endif
92
+
93
+ // Compile time check whether msg_t fits into zmq_msg_t.
94
+ typedef char check_msg_t_size
95
+ [sizeof (zmq::msg_t) == sizeof (zmq_msg_t) ? 1 : -1];
96
+
97
+
98
+ void zmq_version (int *major_, int *minor_, int *patch_)
99
+ {
100
+ *major_ = ZMQ_VERSION_MAJOR;
101
+ *minor_ = ZMQ_VERSION_MINOR;
102
+ *patch_ = ZMQ_VERSION_PATCH;
103
+ }
104
+
105
+
106
+ const char *zmq_strerror (int errnum_)
107
+ {
108
+ return zmq::errno_to_string (errnum_);
109
+ }
110
+
111
+ int zmq_errno ()
112
+ {
113
+ return errno;
114
+ }
115
+
116
+
117
+ // New context API
118
+
119
+ void *zmq_ctx_new (void)
120
+ {
121
+ #if defined ZMQ_HAVE_OPENPGM
122
+
123
+ // Init PGM transport. Ensure threading and timer are enabled. Find PGM
124
+ // protocol ID. Note that if you want to use gettimeofday and sleep for
125
+ // openPGM timing, set environment variables PGM_TIMER to "GTOD" and
126
+ // PGM_SLEEP to "USLEEP".
127
+ pgm_error_t *pgm_error = NULL;
128
+ const bool ok = pgm_init (&pgm_error);
129
+ if (ok != TRUE) {
130
+
131
+ // Invalid parameters don't set pgm_error_t
132
+ zmq_assert (pgm_error != NULL);
133
+ if (pgm_error->domain == PGM_ERROR_DOMAIN_TIME && (
134
+ pgm_error->code == PGM_ERROR_FAILED)) {
135
+
136
+ // Failed to access RTC or HPET device.
137
+ pgm_error_free (pgm_error);
138
+ errno = EINVAL;
139
+ return NULL;
140
+ }
141
+
142
+ // PGM_ERROR_DOMAIN_ENGINE: WSAStartup errors or missing WSARecvMsg.
143
+ zmq_assert (false);
144
+ }
145
+ #endif
146
+
147
+ #ifdef ZMQ_HAVE_WINDOWS
148
+ // Intialise Windows sockets. Note that WSAStartup can be called multiple
149
+ // times given that WSACleanup will be called for each WSAStartup.
150
+ // We do this before the ctx constructor since its embedded mailbox_t
151
+ // object needs Winsock to be up and running.
152
+ WORD version_requested = MAKEWORD (2, 2);
153
+ WSADATA wsa_data;
154
+ int rc = WSAStartup (version_requested, &wsa_data);
155
+ zmq_assert (rc == 0);
156
+ zmq_assert (LOBYTE (wsa_data.wVersion) == 2 &&
157
+ HIBYTE (wsa_data.wVersion) == 2);
158
+ #endif
159
+
160
+ // Create 0MQ context.
161
+ zmq::ctx_t *ctx = new (std::nothrow) zmq::ctx_t;
162
+ alloc_assert (ctx);
163
+ return ctx;
164
+ }
165
+
166
+ int zmq_ctx_destroy (void *ctx_)
167
+ {
168
+ if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
169
+ errno = EFAULT;
170
+ return -1;
171
+ }
172
+
173
+ int rc = ((zmq::ctx_t*) ctx_)->terminate ();
174
+ int en = errno;
175
+
176
+ // Shut down only if termination was not interrupted by a signal.
177
+ if (!rc || en != EINTR) {
178
+ #ifdef ZMQ_HAVE_WINDOWS
179
+ // On Windows, uninitialise socket layer.
180
+ rc = WSACleanup ();
181
+ wsa_assert (rc != SOCKET_ERROR);
182
+ #endif
183
+
184
+ #if defined ZMQ_HAVE_OPENPGM
185
+ // Shut down the OpenPGM library.
186
+ if (pgm_shutdown () != TRUE)
187
+ zmq_assert (false);
188
+ #endif
189
+ }
190
+
191
+ errno = en;
192
+ return rc;
193
+ }
194
+
195
+ int zmq_ctx_set (void *ctx_, int option_, int optval_)
196
+ {
197
+ if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
198
+ errno = EFAULT;
199
+ return -1;
200
+ }
201
+ return ((zmq::ctx_t*) ctx_)->set (option_, optval_);
202
+ }
203
+
204
+ int zmq_ctx_get (void *ctx_, int option_)
205
+ {
206
+ if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
207
+ errno = EFAULT;
208
+ return -1;
209
+ }
210
+ return ((zmq::ctx_t*) ctx_)->get (option_);
211
+ }
212
+
213
+ // Stable/legacy context API
214
+
215
+ void *zmq_init (int io_threads_)
216
+ {
217
+ if (io_threads_ >= 0) {
218
+ void *ctx = zmq_ctx_new ();
219
+ zmq_ctx_set (ctx, ZMQ_IO_THREADS, io_threads_);
220
+ return ctx;
221
+ }
222
+ errno = EINVAL;
223
+ return NULL;
224
+ }
225
+
226
+ int zmq_term (void *ctx_)
227
+ {
228
+ return zmq_ctx_destroy (ctx_);
229
+ }
230
+
231
+
232
+ // Sockets
233
+
234
+ void *zmq_socket (void *ctx_, int type_)
235
+ {
236
+ if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
237
+ errno = EFAULT;
238
+ return NULL;
239
+ }
240
+ zmq::ctx_t *ctx = (zmq::ctx_t*) ctx_;
241
+ zmq::socket_base_t *s = ctx->create_socket (type_);
242
+ return (void *) s;
243
+ }
244
+
245
+ int zmq_close (void *s_)
246
+ {
247
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
248
+ errno = ENOTSOCK;
249
+ return -1;
250
+ }
251
+ ((zmq::socket_base_t*) s_)->close ();
252
+ return 0;
253
+ }
254
+
255
+ int zmq_setsockopt (void *s_, int option_, const void *optval_,
256
+ size_t optvallen_)
257
+ {
258
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
259
+ errno = ENOTSOCK;
260
+ return -1;
261
+ }
262
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
263
+ int result = s->setsockopt (option_, optval_, optvallen_);
264
+ return result;
265
+ }
266
+
267
+ int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_)
268
+ {
269
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
270
+ errno = ENOTSOCK;
271
+ return -1;
272
+ }
273
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
274
+ int result = s->getsockopt (option_, optval_, optvallen_);
275
+ return result;
276
+ }
277
+
278
+ int zmq_socket_monitor (void *s_, const char *addr_, int events_)
279
+ {
280
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
281
+ errno = ENOTSOCK;
282
+ return -1;
283
+ }
284
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
285
+ int result = s->monitor (addr_, events_);
286
+ return result;
287
+ }
288
+
289
+ int zmq_bind (void *s_, const char *addr_)
290
+ {
291
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
292
+ errno = ENOTSOCK;
293
+ return -1;
294
+ }
295
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
296
+ int result = s->bind (addr_);
297
+ return result;
298
+ }
299
+
300
+ int zmq_connect (void *s_, const char *addr_)
301
+ {
302
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
303
+ errno = ENOTSOCK;
304
+ return -1;
305
+ }
306
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
307
+ int result = s->connect (addr_);
308
+ return result;
309
+ }
310
+
311
+ int zmq_unbind (void *s_, const char *addr_)
312
+ {
313
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
314
+ errno = ENOTSOCK;
315
+ return -1;
316
+ }
317
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
318
+ return s->term_endpoint (addr_);
319
+ }
320
+
321
+ int zmq_disconnect (void *s_, const char *addr_)
322
+ {
323
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
324
+ errno = ENOTSOCK;
325
+ return -1;
326
+ }
327
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
328
+ return s->term_endpoint (addr_);
329
+ }
330
+
331
+ // Sending functions.
332
+
333
+ static int
334
+ s_sendmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_)
335
+ {
336
+ int sz = (int) zmq_msg_size (msg_);
337
+ int rc = s_->send ((zmq::msg_t*) msg_, flags_);
338
+ if (unlikely (rc < 0))
339
+ return -1;
340
+ return sz;
341
+ }
342
+
343
+ /* To be deprecated once zmq_msg_send() is stable */
344
+ int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_)
345
+ {
346
+ return zmq_msg_send (msg_, s_, flags_);
347
+ }
348
+
349
+ int zmq_send (void *s_, const void *buf_, size_t len_, int flags_)
350
+ {
351
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
352
+ errno = ENOTSOCK;
353
+ return -1;
354
+ }
355
+ zmq_msg_t msg;
356
+ int rc = zmq_msg_init_size (&msg, len_);
357
+ if (rc != 0)
358
+ return -1;
359
+ memcpy (zmq_msg_data (&msg), buf_, len_);
360
+
361
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
362
+ rc = s_sendmsg (s, &msg, flags_);
363
+ if (unlikely (rc < 0)) {
364
+ int err = errno;
365
+ int rc2 = zmq_msg_close (&msg);
366
+ errno_assert (rc2 == 0);
367
+ errno = err;
368
+ return -1;
369
+ }
370
+
371
+ // Note the optimisation here. We don't close the msg object as it is
372
+ // empty anyway. This may change when implementation of zmq_msg_t changes.
373
+ return rc;
374
+ }
375
+
376
+ // Send multiple messages.
377
+ //
378
+ // If flag bit ZMQ_SNDMORE is set the vector is treated as
379
+ // a single multi-part message, i.e. the last message has
380
+ // ZMQ_SNDMORE bit switched off.
381
+ //
382
+ int zmq_sendiov (void *s_, iovec *a_, size_t count_, int flags_)
383
+ {
384
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
385
+ errno = ENOTSOCK;
386
+ return -1;
387
+ }
388
+ int rc = 0;
389
+ zmq_msg_t msg;
390
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
391
+
392
+ for (size_t i = 0; i < count_; ++i) {
393
+ rc = zmq_msg_init_size (&msg, a_[i].iov_len);
394
+ if (rc != 0) {
395
+ rc = -1;
396
+ break;
397
+ }
398
+ memcpy (zmq_msg_data (&msg), a_[i].iov_base, a_[i].iov_len);
399
+ if (i == count_ - 1)
400
+ flags_ = flags_ & ~ZMQ_SNDMORE;
401
+ rc = s_sendmsg (s, &msg, flags_);
402
+ if (unlikely (rc < 0)) {
403
+ int err = errno;
404
+ int rc2 = zmq_msg_close (&msg);
405
+ errno_assert (rc2 == 0);
406
+ errno = err;
407
+ rc = -1;
408
+ break;
409
+ }
410
+ }
411
+ return rc;
412
+ }
413
+
414
+ // Receiving functions.
415
+
416
+ static int
417
+ s_recvmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_)
418
+ {
419
+ int rc = s_->recv ((zmq::msg_t*) msg_, flags_);
420
+ if (unlikely (rc < 0))
421
+ return -1;
422
+ return (int) zmq_msg_size (msg_);
423
+ }
424
+
425
+ /* To be deprecated once zmq_msg_recv() is stable */
426
+ int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_)
427
+ {
428
+ return zmq_msg_recv (msg_, s_, flags_);
429
+ }
430
+
431
+
432
+ int zmq_recv (void *s_, void *buf_, size_t len_, int flags_)
433
+ {
434
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
435
+ errno = ENOTSOCK;
436
+ return -1;
437
+ }
438
+ zmq_msg_t msg;
439
+ int rc = zmq_msg_init (&msg);
440
+ errno_assert (rc == 0);
441
+
442
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
443
+ int nbytes = s_recvmsg (s, &msg, flags_);
444
+ if (unlikely (nbytes < 0)) {
445
+ int err = errno;
446
+ rc = zmq_msg_close (&msg);
447
+ errno_assert (rc == 0);
448
+ errno = err;
449
+ return -1;
450
+ }
451
+
452
+ // At the moment an oversized message is silently truncated.
453
+ // TODO: Build in a notification mechanism to report the overflows.
454
+ size_t to_copy = size_t (nbytes) < len_ ? size_t (nbytes) : len_;
455
+ memcpy (buf_, zmq_msg_data (&msg), to_copy);
456
+
457
+ rc = zmq_msg_close (&msg);
458
+ errno_assert (rc == 0);
459
+
460
+ return nbytes;
461
+ }
462
+
463
+ // Receive a multi-part message
464
+ //
465
+ // Receives up to *count_ parts of a multi-part message.
466
+ // Sets *count_ to the actual number of parts read.
467
+ // ZMQ_RCVMORE is set to indicate if a complete multi-part message was read.
468
+ // Returns number of message parts read, or -1 on error.
469
+ //
470
+ // Note: even if -1 is returned, some parts of the message
471
+ // may have been read. Therefore the client must consult
472
+ // *count_ to retrieve message parts successfully read,
473
+ // even if -1 is returned.
474
+ //
475
+ // The iov_base* buffers of each iovec *a_ filled in by this
476
+ // function may be freed using free().
477
+ //
478
+ // Implementation note: We assume zmq::msg_t buffer allocated
479
+ // by zmq::recvmsg can be freed by free().
480
+ // We assume it is safe to steal these buffers by simply
481
+ // not closing the zmq::msg_t.
482
+ //
483
+ int zmq_recviov (void *s_, iovec *a_, size_t *count_, int flags_)
484
+ {
485
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
486
+ errno = ENOTSOCK;
487
+ return -1;
488
+ }
489
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
490
+
491
+ size_t count = *count_;
492
+ int nread = 0;
493
+ bool recvmore = true;
494
+
495
+ *count_ = 0;
496
+
497
+ for (size_t i = 0; recvmore && i < count; ++i) {
498
+ // Cheat! We never close any msg
499
+ // because we want to steal the buffer.
500
+ zmq_msg_t msg;
501
+ int rc = zmq_msg_init (&msg);
502
+ errno_assert (rc == 0);
503
+
504
+ int nbytes = s_recvmsg (s, &msg, flags_);
505
+ if (unlikely (nbytes < 0)) {
506
+ int err = errno;
507
+ rc = zmq_msg_close (&msg);
508
+ errno_assert (rc == 0);
509
+ errno = err;
510
+ nread = -1;
511
+ break;
512
+ }
513
+ ++*count_;
514
+ ++nread;
515
+
516
+ // Cheat: acquire zmq_msg buffer.
517
+ a_[i].iov_base = static_cast<char *> (zmq_msg_data (&msg));
518
+ a_[i].iov_len = zmq_msg_size (&msg);
519
+
520
+ // Assume zmq_socket ZMQ_RVCMORE is properly set.
521
+ recvmore = ((zmq::msg_t*) (void *) &msg)->flags () & zmq::msg_t::more;
522
+ }
523
+ return nread;
524
+ }
525
+
526
+ // Message manipulators.
527
+
528
+ int zmq_msg_init (zmq_msg_t *msg_)
529
+ {
530
+ return ((zmq::msg_t*) msg_)->init ();
531
+ }
532
+
533
+ int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_)
534
+ {
535
+ return ((zmq::msg_t*) msg_)->init_size (size_);
536
+ }
537
+
538
+ int zmq_msg_init_data (zmq_msg_t *msg_, void *data_, size_t size_,
539
+ zmq_free_fn *ffn_, void *hint_)
540
+ {
541
+ return ((zmq::msg_t*) msg_)->init_data (data_, size_, ffn_, hint_);
542
+ }
543
+
544
+ int zmq_msg_send (zmq_msg_t *msg_, void *s_, int flags_)
545
+ {
546
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
547
+ errno = ENOTSOCK;
548
+ return -1;
549
+ }
550
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
551
+ int result = s_sendmsg (s, msg_, flags_);
552
+ return result;
553
+ }
554
+
555
+ int zmq_msg_recv (zmq_msg_t *msg_, void *s_, int flags_)
556
+ {
557
+ if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
558
+ errno = ENOTSOCK;
559
+ return -1;
560
+ }
561
+ zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
562
+ int result = s_recvmsg (s, msg_, flags_);
563
+ return result;
564
+ }
565
+
566
+ int zmq_msg_close (zmq_msg_t *msg_)
567
+ {
568
+ return ((zmq::msg_t*) msg_)->close ();
569
+ }
570
+
571
+ int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_)
572
+ {
573
+ return ((zmq::msg_t*) dest_)->move (*(zmq::msg_t*) src_);
574
+ }
575
+
576
+ int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_)
577
+ {
578
+ return ((zmq::msg_t*) dest_)->copy (*(zmq::msg_t*) src_);
579
+ }
580
+
581
+ void *zmq_msg_data (zmq_msg_t *msg_)
582
+ {
583
+ return ((zmq::msg_t*) msg_)->data ();
584
+ }
585
+
586
+ size_t zmq_msg_size (zmq_msg_t *msg_)
587
+ {
588
+ return ((zmq::msg_t*) msg_)->size ();
589
+ }
590
+
591
+ int zmq_msg_more (zmq_msg_t *msg_)
592
+ {
593
+ return zmq_msg_get (msg_, ZMQ_MORE);
594
+ }
595
+
596
+ int zmq_msg_get (zmq_msg_t *msg_, int option_)
597
+ {
598
+ switch (option_) {
599
+ case ZMQ_MORE:
600
+ return (((zmq::msg_t*) msg_)->flags () & zmq::msg_t::more)? 1: 0;
601
+ default:
602
+ errno = EINVAL;
603
+ return -1;
604
+ }
605
+ }
606
+
607
+ int zmq_msg_set (zmq_msg_t *, int, int)
608
+ {
609
+ // No options supported at present
610
+ errno = EINVAL;
611
+ return -1;
612
+ }
613
+
614
+ // Polling.
615
+
616
+ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
617
+ {
618
+ #if defined ZMQ_POLL_BASED_ON_POLL
619
+ if (unlikely (nitems_ < 0)) {
620
+ errno = EINVAL;
621
+ return -1;
622
+ }
623
+ if (unlikely (nitems_ == 0)) {
624
+ if (timeout_ == 0)
625
+ return 0;
626
+ #if defined ZMQ_HAVE_WINDOWS
627
+ Sleep (timeout_ > 0 ? timeout_ : INFINITE);
628
+ return 0;
629
+ #elif defined ZMQ_HAVE_ANDROID
630
+ usleep (timeout_ * 1000);
631
+ return 0;
632
+ #else
633
+ return usleep (timeout_ * 1000);
634
+ #endif
635
+ }
636
+
637
+ if (!items_) {
638
+ errno = EFAULT;
639
+ return -1;
640
+ }
641
+
642
+ zmq::clock_t clock;
643
+ uint64_t now = 0;
644
+ uint64_t end = 0;
645
+
646
+ pollfd *pollfds = (pollfd*) malloc (nitems_ * sizeof (pollfd));
647
+ alloc_assert (pollfds);
648
+
649
+ // Build pollset for poll () system call.
650
+ for (int i = 0; i != nitems_; i++) {
651
+
652
+ // If the poll item is a 0MQ socket, we poll on the file descriptor
653
+ // retrieved by the ZMQ_FD socket option.
654
+ if (items_ [i].socket) {
655
+ size_t zmq_fd_size = sizeof (zmq::fd_t);
656
+ if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &pollfds [i].fd,
657
+ &zmq_fd_size) == -1) {
658
+ free (pollfds);
659
+ return -1;
660
+ }
661
+ pollfds [i].events = items_ [i].events ? POLLIN : 0;
662
+ }
663
+ // Else, the poll item is a raw file descriptor. Just convert the
664
+ // events to normal POLLIN/POLLOUT for poll ().
665
+ else {
666
+ pollfds [i].fd = items_ [i].fd;
667
+ pollfds [i].events =
668
+ (items_ [i].events & ZMQ_POLLIN ? POLLIN : 0) |
669
+ (items_ [i].events & ZMQ_POLLOUT ? POLLOUT : 0);
670
+ }
671
+ }
672
+
673
+ bool first_pass = true;
674
+ int nevents = 0;
675
+
676
+ while (true) {
677
+ // Compute the timeout for the subsequent poll.
678
+ int timeout;
679
+ if (first_pass)
680
+ timeout = 0;
681
+ else
682
+ if (timeout_ < 0)
683
+ timeout = -1;
684
+ else
685
+ timeout = end - now;
686
+
687
+ // Wait for events.
688
+ while (true) {
689
+ int rc = poll (pollfds, nitems_, timeout);
690
+ if (rc == -1 && errno == EINTR) {
691
+ free (pollfds);
692
+ return -1;
693
+ }
694
+ errno_assert (rc >= 0);
695
+ break;
696
+ }
697
+ // Check for the events.
698
+ for (int i = 0; i != nitems_; i++) {
699
+
700
+ items_ [i].revents = 0;
701
+
702
+ // The poll item is a 0MQ socket. Retrieve pending events
703
+ // using the ZMQ_EVENTS socket option.
704
+ if (items_ [i].socket) {
705
+ size_t zmq_events_size = sizeof (uint32_t);
706
+ uint32_t zmq_events;
707
+ if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
708
+ &zmq_events_size) == -1) {
709
+ free (pollfds);
710
+ return -1;
711
+ }
712
+ if ((items_ [i].events & ZMQ_POLLOUT) &&
713
+ (zmq_events & ZMQ_POLLOUT))
714
+ items_ [i].revents |= ZMQ_POLLOUT;
715
+ if ((items_ [i].events & ZMQ_POLLIN) &&
716
+ (zmq_events & ZMQ_POLLIN))
717
+ items_ [i].revents |= ZMQ_POLLIN;
718
+ }
719
+ // Else, the poll item is a raw file descriptor, simply convert
720
+ // the events to zmq_pollitem_t-style format.
721
+ else {
722
+ if (pollfds [i].revents & POLLIN)
723
+ items_ [i].revents |= ZMQ_POLLIN;
724
+ if (pollfds [i].revents & POLLOUT)
725
+ items_ [i].revents |= ZMQ_POLLOUT;
726
+ if (pollfds [i].revents & ~(POLLIN | POLLOUT))
727
+ items_ [i].revents |= ZMQ_POLLERR;
728
+ }
729
+
730
+ if (items_ [i].revents)
731
+ nevents++;
732
+ }
733
+
734
+ // If timout is zero, exit immediately whether there are events or not.
735
+ if (timeout_ == 0)
736
+ break;
737
+
738
+ // If there are events to return, we can exit immediately.
739
+ if (nevents)
740
+ break;
741
+
742
+ // At this point we are meant to wait for events but there are none.
743
+ // If timeout is infinite we can just loop until we get some events.
744
+ if (timeout_ < 0) {
745
+ if (first_pass)
746
+ first_pass = false;
747
+ continue;
748
+ }
749
+
750
+ // The timeout is finite and there are no events. In the first pass
751
+ // we get a timestamp of when the polling have begun. (We assume that
752
+ // first pass have taken negligible time). We also compute the time
753
+ // when the polling should time out.
754
+ if (first_pass) {
755
+ now = clock.now_ms ();
756
+ end = now + timeout_;
757
+ if (now == end)
758
+ break;
759
+ first_pass = false;
760
+ continue;
761
+ }
762
+
763
+ // Find out whether timeout have expired.
764
+ now = clock.now_ms ();
765
+ if (now >= end)
766
+ break;
767
+ }
768
+
769
+ free (pollfds);
770
+ return nevents;
771
+
772
+ #elif defined ZMQ_POLL_BASED_ON_SELECT
773
+
774
+ if (unlikely (nitems_ < 0)) {
775
+ errno = EINVAL;
776
+ return -1;
777
+ }
778
+ if (unlikely (nitems_ == 0)) {
779
+ if (timeout_ == 0)
780
+ return 0;
781
+ #if defined ZMQ_HAVE_WINDOWS
782
+ Sleep (timeout_ > 0 ? timeout_ : INFINITE);
783
+ return 0;
784
+ #else
785
+ return usleep (timeout_ * 1000);
786
+ #endif
787
+ }
788
+ zmq::clock_t clock;
789
+ uint64_t now = 0;
790
+ uint64_t end = 0;
791
+
792
+ // Ensure we do not attempt to select () on more than FD_SETSIZE
793
+ // file descriptors.
794
+ zmq_assert (nitems_ <= FD_SETSIZE);
795
+
796
+ fd_set pollset_in;
797
+ FD_ZERO (&pollset_in);
798
+ fd_set pollset_out;
799
+ FD_ZERO (&pollset_out);
800
+ fd_set pollset_err;
801
+ FD_ZERO (&pollset_err);
802
+
803
+ zmq::fd_t maxfd = 0;
804
+
805
+ // Build the fd_sets for passing to select ().
806
+ for (int i = 0; i != nitems_; i++) {
807
+
808
+ // If the poll item is a 0MQ socket we are interested in input on the
809
+ // notification file descriptor retrieved by the ZMQ_FD socket option.
810
+ if (items_ [i].socket) {
811
+ size_t zmq_fd_size = sizeof (zmq::fd_t);
812
+ zmq::fd_t notify_fd;
813
+ if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &notify_fd,
814
+ &zmq_fd_size) == -1)
815
+ return -1;
816
+ if (items_ [i].events) {
817
+ FD_SET (notify_fd, &pollset_in);
818
+ if (maxfd < notify_fd)
819
+ maxfd = notify_fd;
820
+ }
821
+ }
822
+ // Else, the poll item is a raw file descriptor. Convert the poll item
823
+ // events to the appropriate fd_sets.
824
+ else {
825
+ if (items_ [i].events & ZMQ_POLLIN)
826
+ FD_SET (items_ [i].fd, &pollset_in);
827
+ if (items_ [i].events & ZMQ_POLLOUT)
828
+ FD_SET (items_ [i].fd, &pollset_out);
829
+ if (items_ [i].events & ZMQ_POLLERR)
830
+ FD_SET (items_ [i].fd, &pollset_err);
831
+ if (maxfd < items_ [i].fd)
832
+ maxfd = items_ [i].fd;
833
+ }
834
+ }
835
+
836
+ bool first_pass = true;
837
+ int nevents = 0;
838
+ fd_set inset, outset, errset;
839
+
840
+ while (true) {
841
+
842
+ // Compute the timeout for the subsequent poll.
843
+ timeval timeout;
844
+ timeval *ptimeout;
845
+ if (first_pass) {
846
+ timeout.tv_sec = 0;
847
+ timeout.tv_usec = 0;
848
+ ptimeout = &timeout;
849
+ }
850
+ else
851
+ if (timeout_ < 0)
852
+ ptimeout = NULL;
853
+ else {
854
+ timeout.tv_sec = (long) ((end - now) / 1000);
855
+ timeout.tv_usec = (long) ((end - now) % 1000 * 1000);
856
+ ptimeout = &timeout;
857
+ }
858
+
859
+ // Wait for events. Ignore interrupts if there's infinite timeout.
860
+ while (true) {
861
+ memcpy (&inset, &pollset_in, sizeof (fd_set));
862
+ memcpy (&outset, &pollset_out, sizeof (fd_set));
863
+ memcpy (&errset, &pollset_err, sizeof (fd_set));
864
+ #if defined ZMQ_HAVE_WINDOWS
865
+ int rc = select (0, &inset, &outset, &errset, ptimeout);
866
+ if (unlikely (rc == SOCKET_ERROR)) {
867
+ errno = zmq::wsa_error_to_errno (WSAGetLastError ());
868
+ wsa_assert (errno == ENOTSOCK);
869
+ return -1;
870
+ }
871
+ #else
872
+ int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout);
873
+ if (unlikely (rc == -1)) {
874
+ errno_assert (errno == EINTR || errno == EBADF);
875
+ return -1;
876
+ }
877
+ #endif
878
+ break;
879
+ }
880
+
881
+ // Check for the events.
882
+ for (int i = 0; i != nitems_; i++) {
883
+
884
+ items_ [i].revents = 0;
885
+
886
+ // The poll item is a 0MQ socket. Retrieve pending events
887
+ // using the ZMQ_EVENTS socket option.
888
+ if (items_ [i].socket) {
889
+ size_t zmq_events_size = sizeof (uint32_t);
890
+ uint32_t zmq_events;
891
+ if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
892
+ &zmq_events_size) == -1)
893
+ return -1;
894
+ if ((items_ [i].events & ZMQ_POLLOUT) &&
895
+ (zmq_events & ZMQ_POLLOUT))
896
+ items_ [i].revents |= ZMQ_POLLOUT;
897
+ if ((items_ [i].events & ZMQ_POLLIN) &&
898
+ (zmq_events & ZMQ_POLLIN))
899
+ items_ [i].revents |= ZMQ_POLLIN;
900
+ }
901
+ // Else, the poll item is a raw file descriptor, simply convert
902
+ // the events to zmq_pollitem_t-style format.
903
+ else {
904
+ if (FD_ISSET (items_ [i].fd, &inset))
905
+ items_ [i].revents |= ZMQ_POLLIN;
906
+ if (FD_ISSET (items_ [i].fd, &outset))
907
+ items_ [i].revents |= ZMQ_POLLOUT;
908
+ if (FD_ISSET (items_ [i].fd, &errset))
909
+ items_ [i].revents |= ZMQ_POLLERR;
910
+ }
911
+
912
+ if (items_ [i].revents)
913
+ nevents++;
914
+ }
915
+
916
+ // If timout is zero, exit immediately whether there are events or not.
917
+ if (timeout_ == 0)
918
+ break;
919
+
920
+ // If there are events to return, we can exit immediately.
921
+ if (nevents)
922
+ break;
923
+
924
+ // At this point we are meant to wait for events but there are none.
925
+ // If timeout is infinite we can just loop until we get some events.
926
+ if (timeout_ < 0) {
927
+ if (first_pass)
928
+ first_pass = false;
929
+ continue;
930
+ }
931
+
932
+ // The timeout is finite and there are no events. In the first pass
933
+ // we get a timestamp of when the polling have begun. (We assume that
934
+ // first pass have taken negligible time). We also compute the time
935
+ // when the polling should time out.
936
+ if (first_pass) {
937
+ now = clock.now_ms ();
938
+ end = now + timeout_;
939
+ if (now == end)
940
+ break;
941
+ first_pass = false;
942
+ continue;
943
+ }
944
+
945
+ // Find out whether timeout have expired.
946
+ now = clock.now_ms ();
947
+ if (now >= end)
948
+ break;
949
+ }
950
+
951
+ return nevents;
952
+
953
+ #else
954
+ // Exotic platforms that support neither poll() nor select().
955
+ errno = ENOTSUP;
956
+ return -1;
957
+ #endif
958
+ }
959
+
960
+ #if defined ZMQ_POLL_BASED_ON_SELECT
961
+ #undef ZMQ_POLL_BASED_ON_SELECT
962
+ #endif
963
+ #if defined ZMQ_POLL_BASED_ON_POLL
964
+ #undef ZMQ_POLL_BASED_ON_POLL
965
+ #endif
966
+
967
+ // The proxy functionality
968
+
969
+ int zmq_proxy (void *frontend_, void *backend_, void *control_)
970
+ {
971
+ if (!frontend_ || !backend_) {
972
+ errno = EFAULT;
973
+ return -1;
974
+ }
975
+ return zmq::proxy (
976
+ (zmq::socket_base_t*) frontend_,
977
+ (zmq::socket_base_t*) backend_,
978
+ (zmq::socket_base_t*) control_);
979
+ }
980
+
981
+ // The deprecated device functionality
982
+
983
+ int zmq_device (int type, void *frontend_, void *backend_)
984
+ {
985
+ return zmq::proxy (
986
+ (zmq::socket_base_t*) frontend_,
987
+ (zmq::socket_base_t*) backend_, NULL);
988
+ }
989
+
990
+ // Callback to free socket event data
991
+
992
+ void zmq_free_event (void *event_data, void *hint)
993
+ {
994
+ zmq_event_t *event = (zmq_event_t *) event_data;
995
+
996
+ switch (event->event) {
997
+ case ZMQ_EVENT_CONNECTED:
998
+ free (event->data.connected.addr);
999
+ break;
1000
+ case ZMQ_EVENT_CONNECT_DELAYED:
1001
+ free (event->data.connect_delayed.addr);
1002
+ break;
1003
+ case ZMQ_EVENT_CONNECT_RETRIED:
1004
+ free (event->data.connect_retried.addr);
1005
+ break;
1006
+ case ZMQ_EVENT_LISTENING:
1007
+ free (event->data.listening.addr);
1008
+ break;
1009
+ case ZMQ_EVENT_BIND_FAILED:
1010
+ free (event->data.bind_failed.addr);
1011
+ break;
1012
+ case ZMQ_EVENT_ACCEPTED:
1013
+ free (event->data.accepted.addr);
1014
+ break;
1015
+ case ZMQ_EVENT_ACCEPT_FAILED:
1016
+ free (event->data.accept_failed.addr);
1017
+ break;
1018
+ case ZMQ_EVENT_CLOSED:
1019
+ free (event->data.closed.addr);
1020
+ break;
1021
+ case ZMQ_EVENT_CLOSE_FAILED:
1022
+ free (event->data.close_failed.addr);
1023
+ break;
1024
+ case ZMQ_EVENT_DISCONNECTED:
1025
+ free (event->data.disconnected.addr);
1026
+ break;
1027
+ }
1028
+ free (event_data);
1029
+ }
1030
+
1031
+ ////////////////////////////////////////////////////////////////////////////////
1032
+ // 0MQ utils - to be used by perf tests
1033
+ ////////////////////////////////////////////////////////////////////////////////
1034
+
1035
+ void zmq_sleep (int seconds_)
1036
+ {
1037
+ #if defined ZMQ_HAVE_WINDOWS
1038
+ Sleep (seconds_ * 1000);
1039
+ #else
1040
+ sleep (seconds_);
1041
+ #endif
1042
+ }
1043
+
1044
+ void *zmq_stopwatch_start ()
1045
+ {
1046
+ uint64_t *watch = (uint64_t*) malloc (sizeof (uint64_t));
1047
+ alloc_assert (watch);
1048
+ *watch = zmq::clock_t::now_us ();
1049
+ return (void*) watch;
1050
+ }
1051
+
1052
+ unsigned long zmq_stopwatch_stop (void *watch_)
1053
+ {
1054
+ uint64_t end = zmq::clock_t::now_us ();
1055
+ uint64_t start = *(uint64_t*) watch_;
1056
+ free (watch_);
1057
+ return (unsigned long) (end - start);
1058
+ }