libzmq 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +703 -0
- data/README.md +31 -0
- data/lib/libzmq.rb +17 -0
- data/lib/libzmq/ffi-rzmq.rb +3 -0
- data/libzmq/Makefile +5 -0
- data/libzmq/extconf.rb +24 -0
- data/libzmq/zeromq-2.1.7/AUTHORS +92 -0
- data/libzmq/zeromq-2.1.7/COPYING +674 -0
- data/libzmq/zeromq-2.1.7/COPYING.LESSER +206 -0
- data/libzmq/zeromq-2.1.7/ChangeLog +15620 -0
- data/libzmq/zeromq-2.1.7/INSTALL +237 -0
- data/libzmq/zeromq-2.1.7/MAINTAINERS +56 -0
- data/libzmq/zeromq-2.1.7/Makefile.am +42 -0
- data/libzmq/zeromq-2.1.7/Makefile.in +779 -0
- data/libzmq/zeromq-2.1.7/NEWS +275 -0
- data/libzmq/zeromq-2.1.7/README +39 -0
- data/libzmq/zeromq-2.1.7/acinclude.m4 +582 -0
- data/libzmq/zeromq-2.1.7/aclocal.m4 +1206 -0
- data/libzmq/zeromq-2.1.7/autogen.sh +45 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/Makefile.am +8 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/Makefile.in +390 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/c_local_lat/c_local_lat.vcproj +176 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/c_local_thr/c_local_thr.vcproj +176 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/c_remote_lat/c_remote_lat.vcproj +176 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/c_remote_thr/c_remote_thr.vcproj +176 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/libzmq/libzmq.vcproj +783 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/msvc.sln +89 -0
- data/libzmq/zeromq-2.1.7/builds/msvc/platform.hpp +32 -0
- data/libzmq/zeromq-2.1.7/builds/redhat/zeromq.spec.in +139 -0
- data/libzmq/zeromq-2.1.7/config/compile +143 -0
- data/libzmq/zeromq-2.1.7/config/config.guess +1502 -0
- data/libzmq/zeromq-2.1.7/config/config.sub +1714 -0
- data/libzmq/zeromq-2.1.7/config/depcomp +630 -0
- data/libzmq/zeromq-2.1.7/config/install-sh +520 -0
- data/libzmq/zeromq-2.1.7/config/libtool.m4 +7377 -0
- data/libzmq/zeromq-2.1.7/config/ltmain.sh +8413 -0
- data/libzmq/zeromq-2.1.7/config/ltoptions.m4 +368 -0
- data/libzmq/zeromq-2.1.7/config/ltsugar.m4 +123 -0
- data/libzmq/zeromq-2.1.7/config/ltversion.m4 +23 -0
- data/libzmq/zeromq-2.1.7/config/lt~obsolete.m4 +92 -0
- data/libzmq/zeromq-2.1.7/config/missing +376 -0
- data/libzmq/zeromq-2.1.7/configure +21645 -0
- data/libzmq/zeromq-2.1.7/configure.in +380 -0
- data/libzmq/zeromq-2.1.7/doc/Makefile.am +46 -0
- data/libzmq/zeromq-2.1.7/doc/Makefile.in +546 -0
- data/libzmq/zeromq-2.1.7/doc/asciidoc.conf +56 -0
- data/libzmq/zeromq-2.1.7/doc/zmq.7 +242 -0
- data/libzmq/zeromq-2.1.7/doc/zmq.html +846 -0
- data/libzmq/zeromq-2.1.7/doc/zmq.txt +218 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_bind.3 +166 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_bind.html +746 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_bind.txt +91 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_close.3 +81 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_close.html +645 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_close.txt +52 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_connect.3 +161 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_connect.html +732 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_connect.txt +89 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_cpp.7 +410 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_cpp.html +765 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_cpp.txt +212 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_device.3 +140 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_device.html +736 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_device.txt +138 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_epgm.7 +209 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_epgm.html +749 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_epgm.txt +162 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_errno.3 +78 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_errno.html +634 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_errno.txt +50 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.3 +944 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.html +1713 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_getsockopt.txt +407 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_init.3 +71 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_init.html +635 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_init.txt +51 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_inproc.7 +115 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_inproc.html +669 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_inproc.txt +89 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_ipc.7 +109 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_ipc.html +662 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_ipc.txt +80 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.3 +81 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.html +647 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_close.txt +55 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.3 +95 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.html +656 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_copy.txt +57 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.3 +76 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.html +633 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_data.txt +48 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.3 +110 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.html +656 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init.txt +65 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.3 +138 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.html +678 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_data.txt +83 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.3 +97 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.html +656 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_init_size.txt +58 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.3 +79 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.html +645 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_move.txt +52 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.3 +76 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.html +633 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_msg_size.txt +48 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_pgm.7 +209 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_pgm.html +749 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_pgm.txt +162 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_poll.3 +204 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_poll.html +755 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_poll.txt +132 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_recv.3 +172 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_recv.html +746 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_recv.txt +121 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_send.3 +185 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_send.html +755 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_send.txt +120 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.3 +878 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.html +1603 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_setsockopt.txt +382 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_socket.3 +779 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_socket.html +1424 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_socket.txt +342 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_strerror.3 +78 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_strerror.html +634 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_strerror.txt +55 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_tcp.7 +244 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_tcp.html +755 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_tcp.txt +162 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_term.3 +135 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_term.html +672 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_term.txt +65 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_version.3 +78 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_version.html +632 -0
- data/libzmq/zeromq-2.1.7/doc/zmq_version.txt +53 -0
- data/libzmq/zeromq-2.1.7/foreign/openpgm/Makefile.am +8 -0
- data/libzmq/zeromq-2.1.7/foreign/openpgm/Makefile.in +588 -0
- data/libzmq/zeromq-2.1.7/foreign/openpgm/libpgm-5.1.115~dfsg.tar.gz +0 -0
- data/libzmq/zeromq-2.1.7/foreign/xmlParser/xmlParser.cpp +2923 -0
- data/libzmq/zeromq-2.1.7/foreign/xmlParser/xmlParser.hpp +762 -0
- data/libzmq/zeromq-2.1.7/include/zmq.h +269 -0
- data/libzmq/zeromq-2.1.7/include/zmq.hpp +301 -0
- data/libzmq/zeromq-2.1.7/include/zmq_utils.h +64 -0
- data/libzmq/zeromq-2.1.7/perf/Makefile.am +21 -0
- data/libzmq/zeromq-2.1.7/perf/Makefile.in +566 -0
- data/libzmq/zeromq-2.1.7/perf/inproc_lat.cpp +232 -0
- data/libzmq/zeromq-2.1.7/perf/inproc_thr.cpp +246 -0
- data/libzmq/zeromq-2.1.7/perf/local_lat.cpp +108 -0
- data/libzmq/zeromq-2.1.7/perf/local_thr.cpp +138 -0
- data/libzmq/zeromq-2.1.7/perf/remote_lat.cpp +121 -0
- data/libzmq/zeromq-2.1.7/perf/remote_thr.cpp +104 -0
- data/libzmq/zeromq-2.1.7/src/Makefile.am +155 -0
- data/libzmq/zeromq-2.1.7/src/Makefile.in +1320 -0
- data/libzmq/zeromq-2.1.7/src/array.hpp +147 -0
- data/libzmq/zeromq-2.1.7/src/atomic_counter.hpp +164 -0
- data/libzmq/zeromq-2.1.7/src/atomic_ptr.hpp +159 -0
- data/libzmq/zeromq-2.1.7/src/blob.hpp +34 -0
- data/libzmq/zeromq-2.1.7/src/clock.cpp +118 -0
- data/libzmq/zeromq-2.1.7/src/clock.hpp +60 -0
- data/libzmq/zeromq-2.1.7/src/command.cpp +39 -0
- data/libzmq/zeromq-2.1.7/src/command.hpp +147 -0
- data/libzmq/zeromq-2.1.7/src/config.hpp +88 -0
- data/libzmq/zeromq-2.1.7/src/connect_session.cpp +119 -0
- data/libzmq/zeromq-2.1.7/src/connect_session.hpp +65 -0
- data/libzmq/zeromq-2.1.7/src/ctx.cpp +322 -0
- data/libzmq/zeromq-2.1.7/src/ctx.hpp +159 -0
- data/libzmq/zeromq-2.1.7/src/decoder.cpp +129 -0
- data/libzmq/zeromq-2.1.7/src/decoder.hpp +207 -0
- data/libzmq/zeromq-2.1.7/src/device.cpp +120 -0
- data/libzmq/zeromq-2.1.7/src/device.hpp +32 -0
- data/libzmq/zeromq-2.1.7/src/devpoll.cpp +190 -0
- data/libzmq/zeromq-2.1.7/src/devpoll.hpp +100 -0
- data/libzmq/zeromq-2.1.7/src/dist.cpp +200 -0
- data/libzmq/zeromq-2.1.7/src/dist.hpp +90 -0
- data/libzmq/zeromq-2.1.7/src/encoder.cpp +90 -0
- data/libzmq/zeromq-2.1.7/src/encoder.hpp +184 -0
- data/libzmq/zeromq-2.1.7/src/epoll.cpp +177 -0
- data/libzmq/zeromq-2.1.7/src/epoll.hpp +96 -0
- data/libzmq/zeromq-2.1.7/src/err.cpp +238 -0
- data/libzmq/zeromq-2.1.7/src/err.hpp +145 -0
- data/libzmq/zeromq-2.1.7/src/fd.hpp +45 -0
- data/libzmq/zeromq-2.1.7/src/fq.cpp +164 -0
- data/libzmq/zeromq-2.1.7/src/fq.hpp +80 -0
- data/libzmq/zeromq-2.1.7/src/i_engine.hpp +53 -0
- data/libzmq/zeromq-2.1.7/src/i_inout.hpp +50 -0
- data/libzmq/zeromq-2.1.7/src/i_poll_events.hpp +46 -0
- data/libzmq/zeromq-2.1.7/src/io_object.cpp +107 -0
- data/libzmq/zeromq-2.1.7/src/io_object.hpp +78 -0
- data/libzmq/zeromq-2.1.7/src/io_thread.cpp +109 -0
- data/libzmq/zeromq-2.1.7/src/io_thread.hpp +88 -0
- data/libzmq/zeromq-2.1.7/src/ip.cpp +339 -0
- data/libzmq/zeromq-2.1.7/src/ip.hpp +68 -0
- data/libzmq/zeromq-2.1.7/src/kqueue.cpp +194 -0
- data/libzmq/zeromq-2.1.7/src/kqueue.hpp +103 -0
- data/libzmq/zeromq-2.1.7/src/lb.cpp +174 -0
- data/libzmq/zeromq-2.1.7/src/lb.hpp +79 -0
- data/libzmq/zeromq-2.1.7/src/libzmq.pc.in +10 -0
- data/libzmq/zeromq-2.1.7/src/likely.hpp +33 -0
- data/libzmq/zeromq-2.1.7/src/mailbox.cpp +382 -0
- data/libzmq/zeromq-2.1.7/src/mailbox.hpp +62 -0
- data/libzmq/zeromq-2.1.7/src/msg_content.hpp +52 -0
- data/libzmq/zeromq-2.1.7/src/mutex.hpp +121 -0
- data/libzmq/zeromq-2.1.7/src/named_session.cpp +85 -0
- data/libzmq/zeromq-2.1.7/src/named_session.hpp +57 -0
- data/libzmq/zeromq-2.1.7/src/object.cpp +467 -0
- data/libzmq/zeromq-2.1.7/src/object.hpp +127 -0
- data/libzmq/zeromq-2.1.7/src/options.cpp +336 -0
- data/libzmq/zeromq-2.1.7/src/options.hpp +87 -0
- data/libzmq/zeromq-2.1.7/src/own.cpp +214 -0
- data/libzmq/zeromq-2.1.7/src/own.hpp +140 -0
- data/libzmq/zeromq-2.1.7/src/pair.cpp +180 -0
- data/libzmq/zeromq-2.1.7/src/pair.hpp +76 -0
- data/libzmq/zeromq-2.1.7/src/pgm_receiver.cpp +259 -0
- data/libzmq/zeromq-2.1.7/src/pgm_receiver.hpp +129 -0
- data/libzmq/zeromq-2.1.7/src/pgm_sender.cpp +215 -0
- data/libzmq/zeromq-2.1.7/src/pgm_sender.hpp +105 -0
- data/libzmq/zeromq-2.1.7/src/pgm_socket.cpp +705 -0
- data/libzmq/zeromq-2.1.7/src/pgm_socket.hpp +118 -0
- data/libzmq/zeromq-2.1.7/src/pipe.cpp +409 -0
- data/libzmq/zeromq-2.1.7/src/pipe.hpp +214 -0
- data/libzmq/zeromq-2.1.7/src/platform.hpp.in +228 -0
- data/libzmq/zeromq-2.1.7/src/poll.cpp +180 -0
- data/libzmq/zeromq-2.1.7/src/poll.hpp +104 -0
- data/libzmq/zeromq-2.1.7/src/poller.hpp +73 -0
- data/libzmq/zeromq-2.1.7/src/poller_base.cpp +99 -0
- data/libzmq/zeromq-2.1.7/src/poller_base.hpp +84 -0
- data/libzmq/zeromq-2.1.7/src/pub.cpp +31 -0
- data/libzmq/zeromq-2.1.7/src/pub.hpp +44 -0
- data/libzmq/zeromq-2.1.7/src/pull.cpp +61 -0
- data/libzmq/zeromq-2.1.7/src/pull.hpp +60 -0
- data/libzmq/zeromq-2.1.7/src/push.cpp +62 -0
- data/libzmq/zeromq-2.1.7/src/push.hpp +59 -0
- data/libzmq/zeromq-2.1.7/src/reaper.cpp +121 -0
- data/libzmq/zeromq-2.1.7/src/reaper.hpp +77 -0
- data/libzmq/zeromq-2.1.7/src/rep.cpp +131 -0
- data/libzmq/zeromq-2.1.7/src/rep.hpp +59 -0
- data/libzmq/zeromq-2.1.7/src/req.cpp +121 -0
- data/libzmq/zeromq-2.1.7/src/req.hpp +58 -0
- data/libzmq/zeromq-2.1.7/src/select.cpp +211 -0
- data/libzmq/zeromq-2.1.7/src/select.hpp +116 -0
- data/libzmq/zeromq-2.1.7/src/semaphore.hpp +189 -0
- data/libzmq/zeromq-2.1.7/src/session.cpp +347 -0
- data/libzmq/zeromq-2.1.7/src/session.hpp +150 -0
- data/libzmq/zeromq-2.1.7/src/socket_base.cpp +811 -0
- data/libzmq/zeromq-2.1.7/src/socket_base.hpp +207 -0
- data/libzmq/zeromq-2.1.7/src/stdint.hpp +63 -0
- data/libzmq/zeromq-2.1.7/src/sub.cpp +75 -0
- data/libzmq/zeromq-2.1.7/src/sub.hpp +50 -0
- data/libzmq/zeromq-2.1.7/src/swap.cpp +325 -0
- data/libzmq/zeromq-2.1.7/src/swap.hpp +123 -0
- data/libzmq/zeromq-2.1.7/src/tcp_connecter.cpp +310 -0
- data/libzmq/zeromq-2.1.7/src/tcp_connecter.hpp +81 -0
- data/libzmq/zeromq-2.1.7/src/tcp_listener.cpp +371 -0
- data/libzmq/zeromq-2.1.7/src/tcp_listener.hpp +73 -0
- data/libzmq/zeromq-2.1.7/src/tcp_socket.cpp +228 -0
- data/libzmq/zeromq-2.1.7/src/tcp_socket.hpp +72 -0
- data/libzmq/zeromq-2.1.7/src/thread.cpp +97 -0
- data/libzmq/zeromq-2.1.7/src/thread.hpp +78 -0
- data/libzmq/zeromq-2.1.7/src/transient_session.cpp +41 -0
- data/libzmq/zeromq-2.1.7/src/transient_session.hpp +52 -0
- data/libzmq/zeromq-2.1.7/src/trie.cpp +181 -0
- data/libzmq/zeromq-2.1.7/src/trie.hpp +59 -0
- data/libzmq/zeromq-2.1.7/src/uuid.cpp +233 -0
- data/libzmq/zeromq-2.1.7/src/uuid.hpp +111 -0
- data/libzmq/zeromq-2.1.7/src/windows.hpp +79 -0
- data/libzmq/zeromq-2.1.7/src/wire.hpp +99 -0
- data/libzmq/zeromq-2.1.7/src/xpub.cpp +76 -0
- data/libzmq/zeromq-2.1.7/src/xpub.hpp +61 -0
- data/libzmq/zeromq-2.1.7/src/xrep.cpp +337 -0
- data/libzmq/zeromq-2.1.7/src/xrep.hpp +116 -0
- data/libzmq/zeromq-2.1.7/src/xreq.cpp +74 -0
- data/libzmq/zeromq-2.1.7/src/xreq.hpp +65 -0
- data/libzmq/zeromq-2.1.7/src/xsub.cpp +172 -0
- data/libzmq/zeromq-2.1.7/src/xsub.hpp +80 -0
- data/libzmq/zeromq-2.1.7/src/ypipe.hpp +209 -0
- data/libzmq/zeromq-2.1.7/src/yqueue.hpp +198 -0
- data/libzmq/zeromq-2.1.7/src/zmq.cpp +798 -0
- data/libzmq/zeromq-2.1.7/src/zmq_connecter.cpp +166 -0
- data/libzmq/zeromq-2.1.7/src/zmq_connecter.hpp +92 -0
- data/libzmq/zeromq-2.1.7/src/zmq_engine.cpp +220 -0
- data/libzmq/zeromq-2.1.7/src/zmq_engine.hpp +87 -0
- data/libzmq/zeromq-2.1.7/src/zmq_init.cpp +216 -0
- data/libzmq/zeromq-2.1.7/src/zmq_init.hpp +93 -0
- data/libzmq/zeromq-2.1.7/src/zmq_listener.cpp +78 -0
- data/libzmq/zeromq-2.1.7/src/zmq_listener.hpp +67 -0
- data/libzmq/zeromq-2.1.7/tests/Makefile.am +30 -0
- data/libzmq/zeromq-2.1.7/tests/Makefile.in +713 -0
- data/libzmq/zeromq-2.1.7/tests/test_hwm.cpp +68 -0
- data/libzmq/zeromq-2.1.7/tests/test_pair_inproc.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_pair_ipc.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_pair_tcp.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_reqrep_inproc.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_reqrep_ipc.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_reqrep_tcp.cpp +31 -0
- data/libzmq/zeromq-2.1.7/tests/test_shutdown_stress.cpp +87 -0
- data/libzmq/zeromq-2.1.7/tests/testutil.hpp +130 -0
- data/libzmq/zeromq-2.1.7/version.sh +21 -0
- data/libzmq/zeromq-2.1.7/zeromq.spec +139 -0
- metadata +348 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007-2011 iMatix Corporation
|
3
|
+
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
|
4
|
+
|
5
|
+
This file is part of 0MQ.
|
6
|
+
|
7
|
+
0MQ is free software; you can redistribute it and/or modify it under
|
8
|
+
the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation; either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
0MQ is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
*/
|
20
|
+
|
21
|
+
#ifndef __ZMQ_YPIPE_HPP_INCLUDED__
|
22
|
+
#define __ZMQ_YPIPE_HPP_INCLUDED__
|
23
|
+
|
24
|
+
#include "atomic_ptr.hpp"
|
25
|
+
#include "yqueue.hpp"
|
26
|
+
#include "platform.hpp"
|
27
|
+
|
28
|
+
namespace zmq
|
29
|
+
{
|
30
|
+
|
31
|
+
// Lock-free queue implementation.
|
32
|
+
// Only a single thread can read from the pipe at any specific moment.
|
33
|
+
// Only a single thread can write to the pipe at any specific moment.
|
34
|
+
// T is the type of the object in the queue.
|
35
|
+
// N is granularity of the pipe, i.e. how many items are needed to
|
36
|
+
// perform next memory allocation.
|
37
|
+
|
38
|
+
template <typename T, int N> class ypipe_t
|
39
|
+
{
|
40
|
+
public:
|
41
|
+
|
42
|
+
// Initialises the pipe.
|
43
|
+
inline ypipe_t ()
|
44
|
+
{
|
45
|
+
// Insert terminator element into the queue.
|
46
|
+
queue.push ();
|
47
|
+
|
48
|
+
// Let all the pointers to point to the terminator.
|
49
|
+
// (unless pipe is dead, in which case c is set to NULL).
|
50
|
+
r = w = f = &queue.back ();
|
51
|
+
c.set (&queue.back ());
|
52
|
+
}
|
53
|
+
|
54
|
+
// The destructor doesn't have to be virtual. It is mad virtual
|
55
|
+
// just to keep ICC and code checking tools from complaining.
|
56
|
+
inline virtual ~ypipe_t ()
|
57
|
+
{
|
58
|
+
}
|
59
|
+
|
60
|
+
// Following function (write) deliberately copies uninitialised data
|
61
|
+
// when used with zmq_msg. Initialising the VSM body for
|
62
|
+
// non-VSM messages won't be good for performance.
|
63
|
+
|
64
|
+
#ifdef ZMQ_HAVE_OPENVMS
|
65
|
+
#pragma message save
|
66
|
+
#pragma message disable(UNINIT)
|
67
|
+
#endif
|
68
|
+
|
69
|
+
// Write an item to the pipe. Don't flush it yet. If incomplete is
|
70
|
+
// set to true the item is assumed to be continued by items
|
71
|
+
// subsequently written to the pipe. Incomplete items are never
|
72
|
+
// flushed down the stream.
|
73
|
+
inline void write (const T &value_, bool incomplete_)
|
74
|
+
{
|
75
|
+
// Place the value to the queue, add new terminator element.
|
76
|
+
queue.back () = value_;
|
77
|
+
queue.push ();
|
78
|
+
|
79
|
+
// Move the "flush up to here" poiter.
|
80
|
+
if (!incomplete_)
|
81
|
+
f = &queue.back ();
|
82
|
+
}
|
83
|
+
|
84
|
+
#ifdef ZMQ_HAVE_OPENVMS
|
85
|
+
#pragma message restore
|
86
|
+
#endif
|
87
|
+
|
88
|
+
// Pop an incomplete item from the pipe. Returns true is such
|
89
|
+
// item exists, false otherwise.
|
90
|
+
inline bool unwrite (T *value_)
|
91
|
+
{
|
92
|
+
if (f == &queue.back ())
|
93
|
+
return false;
|
94
|
+
queue.unpush ();
|
95
|
+
*value_ = queue.back ();
|
96
|
+
return true;
|
97
|
+
}
|
98
|
+
|
99
|
+
// Flush all the completed items into the pipe. Returns false if
|
100
|
+
// the reader thread is sleeping. In that case, caller is obliged to
|
101
|
+
// wake the reader up before using the pipe again.
|
102
|
+
inline bool flush ()
|
103
|
+
{
|
104
|
+
// If there are no un-flushed items, do nothing.
|
105
|
+
if (w == f)
|
106
|
+
return true;
|
107
|
+
|
108
|
+
// Try to set 'c' to 'f'.
|
109
|
+
if (c.cas (w, f) != w) {
|
110
|
+
|
111
|
+
// Compare-and-swap was unseccessful because 'c' is NULL.
|
112
|
+
// This means that the reader is asleep. Therefore we don't
|
113
|
+
// care about thread-safeness and update c in non-atomic
|
114
|
+
// manner. We'll return false to let the caller know
|
115
|
+
// that reader is sleeping.
|
116
|
+
c.set (f);
|
117
|
+
w = f;
|
118
|
+
return false;
|
119
|
+
}
|
120
|
+
|
121
|
+
// Reader is alive. Nothing special to do now. Just move
|
122
|
+
// the 'first un-flushed item' pointer to 'f'.
|
123
|
+
w = f;
|
124
|
+
return true;
|
125
|
+
}
|
126
|
+
|
127
|
+
// Check whether item is available for reading.
|
128
|
+
inline bool check_read ()
|
129
|
+
{
|
130
|
+
// Was the value prefetched already? If so, return.
|
131
|
+
if (&queue.front () != r && r)
|
132
|
+
return true;
|
133
|
+
|
134
|
+
// There's no prefetched value, so let us prefetch more values.
|
135
|
+
// Prefetching is to simply retrieve the
|
136
|
+
// pointer from c in atomic fashion. If there are no
|
137
|
+
// items to prefetch, set c to NULL (using compare-and-swap).
|
138
|
+
r = c.cas (&queue.front (), NULL);
|
139
|
+
|
140
|
+
// If there are no elements prefetched, exit.
|
141
|
+
// During pipe's lifetime r should never be NULL, however,
|
142
|
+
// it can happen during pipe shutdown when items
|
143
|
+
// are being deallocated.
|
144
|
+
if (&queue.front () == r || !r)
|
145
|
+
return false;
|
146
|
+
|
147
|
+
// There was at least one value prefetched.
|
148
|
+
return true;
|
149
|
+
}
|
150
|
+
|
151
|
+
// Reads an item from the pipe. Returns false if there is no value.
|
152
|
+
// available.
|
153
|
+
inline bool read (T *value_)
|
154
|
+
{
|
155
|
+
// Try to prefetch a value.
|
156
|
+
if (!check_read ())
|
157
|
+
return false;
|
158
|
+
|
159
|
+
// There was at least one value prefetched.
|
160
|
+
// Return it to the caller.
|
161
|
+
*value_ = queue.front ();
|
162
|
+
queue.pop ();
|
163
|
+
return true;
|
164
|
+
}
|
165
|
+
|
166
|
+
// Applies the function fn to the first elemenent in the pipe
|
167
|
+
// and returns the value returned by the fn.
|
168
|
+
// The pipe mustn't be empty or the function crashes.
|
169
|
+
inline bool probe (bool (*fn)(T &))
|
170
|
+
{
|
171
|
+
bool rc = check_read ();
|
172
|
+
zmq_assert (rc);
|
173
|
+
|
174
|
+
return (*fn) (queue.front ());
|
175
|
+
}
|
176
|
+
|
177
|
+
protected:
|
178
|
+
|
179
|
+
// Allocation-efficient queue to store pipe items.
|
180
|
+
// Front of the queue points to the first prefetched item, back of
|
181
|
+
// the pipe points to last un-flushed item. Front is used only by
|
182
|
+
// reader thread, while back is used only by writer thread.
|
183
|
+
yqueue_t <T, N> queue;
|
184
|
+
|
185
|
+
// Points to the first un-flushed item. This variable is used
|
186
|
+
// exclusively by writer thread.
|
187
|
+
T *w;
|
188
|
+
|
189
|
+
// Points to the first un-prefetched item. This variable is used
|
190
|
+
// exclusively by reader thread.
|
191
|
+
T *r;
|
192
|
+
|
193
|
+
// Points to the first item to be flushed in the future.
|
194
|
+
T *f;
|
195
|
+
|
196
|
+
// The single point of contention between writer and reader thread.
|
197
|
+
// Points past the last flushed item. If it is NULL,
|
198
|
+
// reader is asleep. This pointer should be always accessed using
|
199
|
+
// atomic operations.
|
200
|
+
atomic_ptr_t <T> c;
|
201
|
+
|
202
|
+
// Disable copying of ypipe object.
|
203
|
+
ypipe_t (const ypipe_t&);
|
204
|
+
const ypipe_t &operator = (const ypipe_t&);
|
205
|
+
};
|
206
|
+
|
207
|
+
}
|
208
|
+
|
209
|
+
#endif
|
@@ -0,0 +1,198 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007-2011 iMatix Corporation
|
3
|
+
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
|
4
|
+
|
5
|
+
This file is part of 0MQ.
|
6
|
+
|
7
|
+
0MQ is free software; you can redistribute it and/or modify it under
|
8
|
+
the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation; either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
0MQ is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
*/
|
20
|
+
|
21
|
+
#ifndef __ZMQ_YQUEUE_HPP_INCLUDED__
|
22
|
+
#define __ZMQ_YQUEUE_HPP_INCLUDED__
|
23
|
+
|
24
|
+
#include <stdlib.h>
|
25
|
+
#include <stddef.h>
|
26
|
+
|
27
|
+
#include "err.hpp"
|
28
|
+
#include "atomic_ptr.hpp"
|
29
|
+
|
30
|
+
namespace zmq
|
31
|
+
{
|
32
|
+
|
33
|
+
// yqueue is an efficient queue implementation. The main goal is
|
34
|
+
// to minimise number of allocations/deallocations needed. Thus yqueue
|
35
|
+
// allocates/deallocates elements in batches of N.
|
36
|
+
//
|
37
|
+
// yqueue allows one thread to use push/back function and another one
|
38
|
+
// to use pop/front functions. However, user must ensure that there's no
|
39
|
+
// pop on the empty queue and that both threads don't access the same
|
40
|
+
// element in unsynchronised manner.
|
41
|
+
//
|
42
|
+
// T is the type of the object in the queue.
|
43
|
+
// N is granularity of the queue (how many pushes have to be done till
|
44
|
+
// actual memory allocation is required).
|
45
|
+
|
46
|
+
template <typename T, int N> class yqueue_t
|
47
|
+
{
|
48
|
+
public:
|
49
|
+
|
50
|
+
// Create the queue.
|
51
|
+
inline yqueue_t ()
|
52
|
+
{
|
53
|
+
begin_chunk = (chunk_t*) malloc (sizeof (chunk_t));
|
54
|
+
alloc_assert (begin_chunk);
|
55
|
+
begin_pos = 0;
|
56
|
+
back_chunk = NULL;
|
57
|
+
back_pos = 0;
|
58
|
+
end_chunk = begin_chunk;
|
59
|
+
end_pos = 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
// Destroy the queue.
|
63
|
+
inline ~yqueue_t ()
|
64
|
+
{
|
65
|
+
while (true) {
|
66
|
+
if (begin_chunk == end_chunk) {
|
67
|
+
free (begin_chunk);
|
68
|
+
break;
|
69
|
+
}
|
70
|
+
chunk_t *o = begin_chunk;
|
71
|
+
begin_chunk = begin_chunk->next;
|
72
|
+
free (o);
|
73
|
+
}
|
74
|
+
|
75
|
+
chunk_t *sc = spare_chunk.xchg (NULL);
|
76
|
+
if (sc)
|
77
|
+
free (sc);
|
78
|
+
}
|
79
|
+
|
80
|
+
// Returns reference to the front element of the queue.
|
81
|
+
// If the queue is empty, behaviour is undefined.
|
82
|
+
inline T &front ()
|
83
|
+
{
|
84
|
+
return begin_chunk->values [begin_pos];
|
85
|
+
}
|
86
|
+
|
87
|
+
// Returns reference to the back element of the queue.
|
88
|
+
// If the queue is empty, behaviour is undefined.
|
89
|
+
inline T &back ()
|
90
|
+
{
|
91
|
+
return back_chunk->values [back_pos];
|
92
|
+
}
|
93
|
+
|
94
|
+
// Adds an element to the back end of the queue.
|
95
|
+
inline void push ()
|
96
|
+
{
|
97
|
+
back_chunk = end_chunk;
|
98
|
+
back_pos = end_pos;
|
99
|
+
|
100
|
+
if (++end_pos != N)
|
101
|
+
return;
|
102
|
+
|
103
|
+
chunk_t *sc = spare_chunk.xchg (NULL);
|
104
|
+
if (sc) {
|
105
|
+
end_chunk->next = sc;
|
106
|
+
sc->prev = end_chunk;
|
107
|
+
} else {
|
108
|
+
end_chunk->next = (chunk_t*) malloc (sizeof (chunk_t));
|
109
|
+
alloc_assert (end_chunk->next);
|
110
|
+
end_chunk->next->prev = end_chunk;
|
111
|
+
}
|
112
|
+
end_chunk = end_chunk->next;
|
113
|
+
end_pos = 0;
|
114
|
+
}
|
115
|
+
|
116
|
+
// Removes element from the back end of the queue. In other words
|
117
|
+
// it rollbacks last push to the queue. Take care: Caller is
|
118
|
+
// responsible for destroying the object being unpushed.
|
119
|
+
// The caller must also guarantee that the queue isn't empty when
|
120
|
+
// unpush is called. It cannot be done automatically as the read
|
121
|
+
// side of the queue can be managed by different, completely
|
122
|
+
// unsynchronised thread.
|
123
|
+
inline void unpush ()
|
124
|
+
{
|
125
|
+
// First, move 'back' one position backwards.
|
126
|
+
if (back_pos)
|
127
|
+
--back_pos;
|
128
|
+
else {
|
129
|
+
back_pos = N - 1;
|
130
|
+
back_chunk = back_chunk->prev;
|
131
|
+
}
|
132
|
+
|
133
|
+
// Now, move 'end' position backwards. Note that obsolete end chunk
|
134
|
+
// is not used as a spare chunk. The analysis shows that doing so
|
135
|
+
// would require free and atomic operation per chunk deallocated
|
136
|
+
// instead of a simple free.
|
137
|
+
if (end_pos)
|
138
|
+
--end_pos;
|
139
|
+
else {
|
140
|
+
end_pos = N - 1;
|
141
|
+
end_chunk = end_chunk->prev;
|
142
|
+
free (end_chunk->next);
|
143
|
+
end_chunk->next = NULL;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
// Removes an element from the front end of the queue.
|
148
|
+
inline void pop ()
|
149
|
+
{
|
150
|
+
if (++ begin_pos == N) {
|
151
|
+
chunk_t *o = begin_chunk;
|
152
|
+
begin_chunk = begin_chunk->next;
|
153
|
+
begin_chunk->prev = NULL;
|
154
|
+
begin_pos = 0;
|
155
|
+
|
156
|
+
// 'o' has been more recently used than spare_chunk,
|
157
|
+
// so for cache reasons we'll get rid of the spare and
|
158
|
+
// use 'o' as the spare.
|
159
|
+
chunk_t *cs = spare_chunk.xchg (o);
|
160
|
+
if (cs)
|
161
|
+
free (cs);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
private:
|
166
|
+
|
167
|
+
// Individual memory chunk to hold N elements.
|
168
|
+
struct chunk_t
|
169
|
+
{
|
170
|
+
T values [N];
|
171
|
+
chunk_t *prev;
|
172
|
+
chunk_t *next;
|
173
|
+
};
|
174
|
+
|
175
|
+
// Back position may point to invalid memory if the queue is empty,
|
176
|
+
// while begin & end positions are always valid. Begin position is
|
177
|
+
// accessed exclusively be queue reader (front/pop), while back and
|
178
|
+
// end positions are accessed exclusively by queue writer (back/push).
|
179
|
+
chunk_t *begin_chunk;
|
180
|
+
int begin_pos;
|
181
|
+
chunk_t *back_chunk;
|
182
|
+
int back_pos;
|
183
|
+
chunk_t *end_chunk;
|
184
|
+
int end_pos;
|
185
|
+
|
186
|
+
// People are likely to produce and consume at similar rates. In
|
187
|
+
// this scenario holding onto the most recently freed chunk saves
|
188
|
+
// us from having to call malloc/free.
|
189
|
+
atomic_ptr_t<chunk_t> spare_chunk;
|
190
|
+
|
191
|
+
// Disable copying of yqueue.
|
192
|
+
yqueue_t (const yqueue_t&);
|
193
|
+
const yqueue_t &operator = (const yqueue_t&);
|
194
|
+
};
|
195
|
+
|
196
|
+
}
|
197
|
+
|
198
|
+
#endif
|
@@ -0,0 +1,798 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007-2011 iMatix Corporation
|
3
|
+
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
|
4
|
+
|
5
|
+
This file is part of 0MQ.
|
6
|
+
|
7
|
+
0MQ is free software; you can redistribute it and/or modify it under
|
8
|
+
the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation; either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
0MQ is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
*/
|
20
|
+
|
21
|
+
#include "platform.hpp"
|
22
|
+
|
23
|
+
// On AIX, poll.h has to be included before zmq.h to get consistent
|
24
|
+
// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents'
|
25
|
+
// instead of 'events' and 'revents' and defines macros to map from POSIX-y
|
26
|
+
// names to AIX-specific names).
|
27
|
+
#if defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\
|
28
|
+
defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\
|
29
|
+
defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\
|
30
|
+
defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\
|
31
|
+
defined ZMQ_HAVE_NETBSD
|
32
|
+
#include <poll.h>
|
33
|
+
#endif
|
34
|
+
|
35
|
+
#include "../include/zmq.h"
|
36
|
+
#include "../include/zmq_utils.h"
|
37
|
+
|
38
|
+
#include <string.h>
|
39
|
+
#include <errno.h>
|
40
|
+
#include <stdlib.h>
|
41
|
+
#include <new>
|
42
|
+
|
43
|
+
#include "device.hpp"
|
44
|
+
#include "socket_base.hpp"
|
45
|
+
#include "msg_content.hpp"
|
46
|
+
#include "stdint.hpp"
|
47
|
+
#include "config.hpp"
|
48
|
+
#include "likely.hpp"
|
49
|
+
#include "clock.hpp"
|
50
|
+
#include "ctx.hpp"
|
51
|
+
#include "err.hpp"
|
52
|
+
#include "fd.hpp"
|
53
|
+
|
54
|
+
#if !defined ZMQ_HAVE_WINDOWS
|
55
|
+
#include <unistd.h>
|
56
|
+
#endif
|
57
|
+
|
58
|
+
#if defined ZMQ_HAVE_OPENPGM
|
59
|
+
#define __PGM_WININT_H__
|
60
|
+
#include <pgm/pgm.h>
|
61
|
+
|
62
|
+
// TODO: OpenPGM redefines bool -- remove this once OpenPGM is fixed.
|
63
|
+
#if defined bool
|
64
|
+
#undef bool
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#endif
|
68
|
+
|
69
|
+
void zmq_version (int *major_, int *minor_, int *patch_)
|
70
|
+
{
|
71
|
+
*major_ = ZMQ_VERSION_MAJOR;
|
72
|
+
*minor_ = ZMQ_VERSION_MINOR;
|
73
|
+
*patch_ = ZMQ_VERSION_PATCH;
|
74
|
+
}
|
75
|
+
|
76
|
+
const char *zmq_strerror (int errnum_)
|
77
|
+
{
|
78
|
+
return zmq::errno_to_string (errnum_);
|
79
|
+
}
|
80
|
+
|
81
|
+
int zmq_msg_init (zmq_msg_t *msg_)
|
82
|
+
{
|
83
|
+
msg_->content = (zmq::msg_content_t*) ZMQ_VSM;
|
84
|
+
msg_->flags = (unsigned char) ~ZMQ_MSG_MASK;
|
85
|
+
msg_->vsm_size = 0;
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
|
89
|
+
int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_)
|
90
|
+
{
|
91
|
+
if (size_ <= ZMQ_MAX_VSM_SIZE) {
|
92
|
+
msg_->content = (zmq::msg_content_t*) ZMQ_VSM;
|
93
|
+
msg_->flags = (unsigned char) ~ZMQ_MSG_MASK;
|
94
|
+
msg_->vsm_size = (uint8_t) size_;
|
95
|
+
}
|
96
|
+
else {
|
97
|
+
msg_->content =
|
98
|
+
(zmq::msg_content_t*) malloc (sizeof (zmq::msg_content_t) + size_);
|
99
|
+
if (!msg_->content) {
|
100
|
+
errno = ENOMEM;
|
101
|
+
return -1;
|
102
|
+
}
|
103
|
+
msg_->flags = (unsigned char) ~ZMQ_MSG_MASK;
|
104
|
+
|
105
|
+
zmq::msg_content_t *content = (zmq::msg_content_t*) msg_->content;
|
106
|
+
content->data = (void*) (content + 1);
|
107
|
+
content->size = size_;
|
108
|
+
content->ffn = NULL;
|
109
|
+
content->hint = NULL;
|
110
|
+
new (&content->refcnt) zmq::atomic_counter_t ();
|
111
|
+
}
|
112
|
+
return 0;
|
113
|
+
}
|
114
|
+
|
115
|
+
int zmq_msg_init_data (zmq_msg_t *msg_, void *data_, size_t size_,
|
116
|
+
zmq_free_fn *ffn_, void *hint_)
|
117
|
+
{
|
118
|
+
msg_->content = (zmq::msg_content_t*) malloc (sizeof (zmq::msg_content_t));
|
119
|
+
alloc_assert (msg_->content);
|
120
|
+
msg_->flags = (unsigned char) ~ZMQ_MSG_MASK;
|
121
|
+
zmq::msg_content_t *content = (zmq::msg_content_t*) msg_->content;
|
122
|
+
content->data = data_;
|
123
|
+
content->size = size_;
|
124
|
+
content->ffn = ffn_;
|
125
|
+
content->hint = hint_;
|
126
|
+
new (&content->refcnt) zmq::atomic_counter_t ();
|
127
|
+
return 0;
|
128
|
+
}
|
129
|
+
|
130
|
+
int zmq_msg_close (zmq_msg_t *msg_)
|
131
|
+
{
|
132
|
+
// Check the validity tag.
|
133
|
+
if (unlikely (msg_->flags | ZMQ_MSG_MASK) != 0xff) {
|
134
|
+
errno = EFAULT;
|
135
|
+
return -1;
|
136
|
+
}
|
137
|
+
|
138
|
+
// For VSMs and delimiters there are no resources to free.
|
139
|
+
if (msg_->content != (zmq::msg_content_t*) ZMQ_DELIMITER &&
|
140
|
+
msg_->content != (zmq::msg_content_t*) ZMQ_VSM) {
|
141
|
+
|
142
|
+
// If the content is not shared, or if it is shared and the reference.
|
143
|
+
// count has dropped to zero, deallocate it.
|
144
|
+
zmq::msg_content_t *content = (zmq::msg_content_t*) msg_->content;
|
145
|
+
if (!(msg_->flags & ZMQ_MSG_SHARED) || !content->refcnt.sub (1)) {
|
146
|
+
|
147
|
+
// We used "placement new" operator to initialize the reference.
|
148
|
+
// counter so we call its destructor now.
|
149
|
+
content->refcnt.~atomic_counter_t ();
|
150
|
+
|
151
|
+
if (content->ffn)
|
152
|
+
content->ffn (content->data, content->hint);
|
153
|
+
free (content);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
// Remove the validity tag from the message.
|
158
|
+
msg_->flags = 0;
|
159
|
+
|
160
|
+
return 0;
|
161
|
+
}
|
162
|
+
|
163
|
+
int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_)
|
164
|
+
{
|
165
|
+
#if 0
|
166
|
+
// Check the validity tags.
|
167
|
+
if (unlikely ((dest_->flags | ZMQ_MSG_MASK) != 0xff ||
|
168
|
+
(src_->flags | ZMQ_MSG_MASK) != 0xff)) {
|
169
|
+
errno = EFAULT;
|
170
|
+
return -1;
|
171
|
+
}
|
172
|
+
#endif
|
173
|
+
zmq_msg_close (dest_);
|
174
|
+
*dest_ = *src_;
|
175
|
+
zmq_msg_init (src_);
|
176
|
+
return 0;
|
177
|
+
}
|
178
|
+
|
179
|
+
int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_)
|
180
|
+
{
|
181
|
+
// Check the validity tags.
|
182
|
+
if (unlikely ((dest_->flags | ZMQ_MSG_MASK) != 0xff ||
|
183
|
+
(src_->flags | ZMQ_MSG_MASK) != 0xff)) {
|
184
|
+
errno = EFAULT;
|
185
|
+
return -1;
|
186
|
+
}
|
187
|
+
|
188
|
+
zmq_msg_close (dest_);
|
189
|
+
|
190
|
+
// VSMs and delimiters require no special handling.
|
191
|
+
if (src_->content != (zmq::msg_content_t*) ZMQ_DELIMITER &&
|
192
|
+
src_->content != (zmq::msg_content_t*) ZMQ_VSM) {
|
193
|
+
|
194
|
+
// One reference is added to shared messages. Non-shared messages
|
195
|
+
// are turned into shared messages and reference count is set to 2.
|
196
|
+
zmq::msg_content_t *content = (zmq::msg_content_t*) src_->content;
|
197
|
+
if (src_->flags & ZMQ_MSG_SHARED)
|
198
|
+
content->refcnt.add (1);
|
199
|
+
else {
|
200
|
+
src_->flags |= ZMQ_MSG_SHARED;
|
201
|
+
content->refcnt.set (2);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
*dest_ = *src_;
|
206
|
+
return 0;
|
207
|
+
}
|
208
|
+
|
209
|
+
void *zmq_msg_data (zmq_msg_t *msg_)
|
210
|
+
{
|
211
|
+
zmq_assert ((msg_->flags | ZMQ_MSG_MASK) == 0xff);
|
212
|
+
|
213
|
+
if (msg_->content == (zmq::msg_content_t*) ZMQ_VSM)
|
214
|
+
return msg_->vsm_data;
|
215
|
+
if (msg_->content == (zmq::msg_content_t*) ZMQ_DELIMITER)
|
216
|
+
return NULL;
|
217
|
+
|
218
|
+
return ((zmq::msg_content_t*) msg_->content)->data;
|
219
|
+
}
|
220
|
+
|
221
|
+
size_t zmq_msg_size (zmq_msg_t *msg_)
|
222
|
+
{
|
223
|
+
zmq_assert ((msg_->flags | ZMQ_MSG_MASK) == 0xff);
|
224
|
+
|
225
|
+
if (msg_->content == (zmq::msg_content_t*) ZMQ_VSM)
|
226
|
+
return msg_->vsm_size;
|
227
|
+
if (msg_->content == (zmq::msg_content_t*) ZMQ_DELIMITER)
|
228
|
+
return 0;
|
229
|
+
|
230
|
+
return ((zmq::msg_content_t*) msg_->content)->size;
|
231
|
+
}
|
232
|
+
|
233
|
+
void *zmq_init (int io_threads_)
|
234
|
+
{
|
235
|
+
if (io_threads_ < 0) {
|
236
|
+
errno = EINVAL;
|
237
|
+
return NULL;
|
238
|
+
}
|
239
|
+
|
240
|
+
#if defined ZMQ_HAVE_OPENPGM
|
241
|
+
|
242
|
+
// Init PGM transport. Ensure threading and timer are enabled. Find PGM
|
243
|
+
// protocol ID. Note that if you want to use gettimeofday and sleep for
|
244
|
+
// openPGM timing, set environment variables PGM_TIMER to "GTOD" and
|
245
|
+
// PGM_SLEEP to "USLEEP".
|
246
|
+
pgm_error_t *pgm_error = NULL;
|
247
|
+
const bool ok = pgm_init (&pgm_error);
|
248
|
+
if (ok != TRUE) {
|
249
|
+
|
250
|
+
// Invalid parameters don't set pgm_error_t
|
251
|
+
zmq_assert (pgm_error != NULL);
|
252
|
+
if (pgm_error->domain == PGM_ERROR_DOMAIN_TIME && (
|
253
|
+
pgm_error->code == PGM_ERROR_FAILED)) {
|
254
|
+
|
255
|
+
// Failed to access RTC or HPET device.
|
256
|
+
pgm_error_free (pgm_error);
|
257
|
+
errno = EINVAL;
|
258
|
+
return NULL;
|
259
|
+
}
|
260
|
+
|
261
|
+
// PGM_ERROR_DOMAIN_ENGINE: WSAStartup errors or missing WSARecvMsg.
|
262
|
+
zmq_assert (false);
|
263
|
+
}
|
264
|
+
#endif
|
265
|
+
|
266
|
+
#ifdef ZMQ_HAVE_WINDOWS
|
267
|
+
// Intialise Windows sockets. Note that WSAStartup can be called multiple
|
268
|
+
// times given that WSACleanup will be called for each WSAStartup.
|
269
|
+
// We do this before the ctx constructor since its embedded mailbox_t
|
270
|
+
// object needs Winsock to be up and running.
|
271
|
+
WORD version_requested = MAKEWORD (2, 2);
|
272
|
+
WSADATA wsa_data;
|
273
|
+
int rc = WSAStartup (version_requested, &wsa_data);
|
274
|
+
zmq_assert (rc == 0);
|
275
|
+
zmq_assert (LOBYTE (wsa_data.wVersion) == 2 &&
|
276
|
+
HIBYTE (wsa_data.wVersion) == 2);
|
277
|
+
#endif
|
278
|
+
|
279
|
+
// Create 0MQ context.
|
280
|
+
zmq::ctx_t *ctx = new (std::nothrow) zmq::ctx_t ((uint32_t) io_threads_);
|
281
|
+
alloc_assert (ctx);
|
282
|
+
return (void*) ctx;
|
283
|
+
}
|
284
|
+
|
285
|
+
int zmq_term (void *ctx_)
|
286
|
+
{
|
287
|
+
if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
|
288
|
+
errno = EFAULT;
|
289
|
+
return -1;
|
290
|
+
}
|
291
|
+
|
292
|
+
int rc = ((zmq::ctx_t*) ctx_)->terminate ();
|
293
|
+
int en = errno;
|
294
|
+
|
295
|
+
#ifdef ZMQ_HAVE_WINDOWS
|
296
|
+
// On Windows, uninitialise socket layer.
|
297
|
+
rc = WSACleanup ();
|
298
|
+
wsa_assert (rc != SOCKET_ERROR);
|
299
|
+
#endif
|
300
|
+
|
301
|
+
#if defined ZMQ_HAVE_OPENPGM
|
302
|
+
// Shut down the OpenPGM library.
|
303
|
+
if (pgm_shutdown () != TRUE)
|
304
|
+
zmq_assert (false);
|
305
|
+
#endif
|
306
|
+
|
307
|
+
errno = en;
|
308
|
+
return rc;
|
309
|
+
}
|
310
|
+
|
311
|
+
void *zmq_socket (void *ctx_, int type_)
|
312
|
+
{
|
313
|
+
if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
|
314
|
+
errno = EFAULT;
|
315
|
+
return NULL;
|
316
|
+
}
|
317
|
+
return (void*) (((zmq::ctx_t*) ctx_)->create_socket (type_));
|
318
|
+
}
|
319
|
+
|
320
|
+
int zmq_close (void *s_)
|
321
|
+
{
|
322
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
323
|
+
errno = ENOTSOCK;
|
324
|
+
return -1;
|
325
|
+
}
|
326
|
+
((zmq::socket_base_t*) s_)->close ();
|
327
|
+
return 0;
|
328
|
+
}
|
329
|
+
|
330
|
+
int zmq_setsockopt (void *s_, int option_, const void *optval_,
|
331
|
+
size_t optvallen_)
|
332
|
+
{
|
333
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
334
|
+
errno = ENOTSOCK;
|
335
|
+
return -1;
|
336
|
+
}
|
337
|
+
return (((zmq::socket_base_t*) s_)->setsockopt (option_, optval_,
|
338
|
+
optvallen_));
|
339
|
+
}
|
340
|
+
|
341
|
+
int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_)
|
342
|
+
{
|
343
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
344
|
+
errno = ENOTSOCK;
|
345
|
+
return -1;
|
346
|
+
}
|
347
|
+
return (((zmq::socket_base_t*) s_)->getsockopt (option_, optval_,
|
348
|
+
optvallen_));
|
349
|
+
}
|
350
|
+
|
351
|
+
int zmq_bind (void *s_, const char *addr_)
|
352
|
+
{
|
353
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
354
|
+
errno = ENOTSOCK;
|
355
|
+
return -1;
|
356
|
+
}
|
357
|
+
return (((zmq::socket_base_t*) s_)->bind (addr_));
|
358
|
+
}
|
359
|
+
|
360
|
+
int zmq_connect (void *s_, const char *addr_)
|
361
|
+
{
|
362
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
363
|
+
errno = ENOTSOCK;
|
364
|
+
return -1;
|
365
|
+
}
|
366
|
+
return (((zmq::socket_base_t*) s_)->connect (addr_));
|
367
|
+
}
|
368
|
+
|
369
|
+
int zmq_send (void *s_, zmq_msg_t *msg_, int flags_)
|
370
|
+
{
|
371
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
372
|
+
errno = ENOTSOCK;
|
373
|
+
return -1;
|
374
|
+
}
|
375
|
+
return (((zmq::socket_base_t*) s_)->send (msg_, flags_));
|
376
|
+
}
|
377
|
+
|
378
|
+
int zmq_recv (void *s_, zmq_msg_t *msg_, int flags_)
|
379
|
+
{
|
380
|
+
if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
|
381
|
+
errno = ENOTSOCK;
|
382
|
+
return -1;
|
383
|
+
}
|
384
|
+
return (((zmq::socket_base_t*) s_)->recv (msg_, flags_));
|
385
|
+
}
|
386
|
+
|
387
|
+
#if defined ZMQ_FORCE_SELECT
|
388
|
+
#define ZMQ_POLL_BASED_ON_SELECT
|
389
|
+
#elif defined ZMQ_FORCE_POLL
|
390
|
+
#define ZMQ_POLL_BASED_ON_POLL
|
391
|
+
#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\
|
392
|
+
defined ZMQ_HAVE_OPENBSD || defined ZMQ_HAVE_SOLARIS ||\
|
393
|
+
defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_QNXNTO ||\
|
394
|
+
defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_AIX ||\
|
395
|
+
defined ZMQ_HAVE_NETBSD
|
396
|
+
#define ZMQ_POLL_BASED_ON_POLL
|
397
|
+
#elif defined ZMQ_HAVE_WINDOWS || defined ZMQ_HAVE_OPENVMS
|
398
|
+
#define ZMQ_POLL_BASED_ON_SELECT
|
399
|
+
#endif
|
400
|
+
|
401
|
+
int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
|
402
|
+
{
|
403
|
+
#if defined ZMQ_POLL_BASED_ON_POLL
|
404
|
+
if (unlikely (nitems_ < 0)) {
|
405
|
+
errno = EINVAL;
|
406
|
+
return -1;
|
407
|
+
}
|
408
|
+
if (unlikely (nitems_ == 0)) {
|
409
|
+
if (timeout_ == 0)
|
410
|
+
return 0;
|
411
|
+
#if defined ZMQ_HAVE_WINDOWS
|
412
|
+
Sleep (timeout_ > 0 ? timeout_ / 1000 : INFINITE);
|
413
|
+
return 0;
|
414
|
+
#else
|
415
|
+
return usleep (timeout_);
|
416
|
+
#endif
|
417
|
+
}
|
418
|
+
|
419
|
+
if (!items_) {
|
420
|
+
errno = EFAULT;
|
421
|
+
return -1;
|
422
|
+
}
|
423
|
+
|
424
|
+
zmq::clock_t clock;
|
425
|
+
uint64_t now = 0;
|
426
|
+
uint64_t end = 0;
|
427
|
+
|
428
|
+
pollfd *pollfds = (pollfd*) malloc (nitems_ * sizeof (pollfd));
|
429
|
+
alloc_assert (pollfds);
|
430
|
+
|
431
|
+
// Build pollset for poll () system call.
|
432
|
+
for (int i = 0; i != nitems_; i++) {
|
433
|
+
|
434
|
+
// If the poll item is a 0MQ socket, we poll on the file descriptor
|
435
|
+
// retrieved by the ZMQ_FD socket option.
|
436
|
+
if (items_ [i].socket) {
|
437
|
+
size_t zmq_fd_size = sizeof (zmq::fd_t);
|
438
|
+
if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &pollfds [i].fd,
|
439
|
+
&zmq_fd_size) == -1) {
|
440
|
+
free (pollfds);
|
441
|
+
return -1;
|
442
|
+
}
|
443
|
+
pollfds [i].events = items_ [i].events ? POLLIN : 0;
|
444
|
+
}
|
445
|
+
// Else, the poll item is a raw file descriptor. Just convert the
|
446
|
+
// events to normal POLLIN/POLLOUT for poll ().
|
447
|
+
else {
|
448
|
+
pollfds [i].fd = items_ [i].fd;
|
449
|
+
pollfds [i].events =
|
450
|
+
(items_ [i].events & ZMQ_POLLIN ? POLLIN : 0) |
|
451
|
+
(items_ [i].events & ZMQ_POLLOUT ? POLLOUT : 0);
|
452
|
+
}
|
453
|
+
}
|
454
|
+
|
455
|
+
bool first_pass = true;
|
456
|
+
int nevents = 0;
|
457
|
+
|
458
|
+
while (true) {
|
459
|
+
|
460
|
+
// Compute the timeout for the subsequent poll.
|
461
|
+
int timeout;
|
462
|
+
if (first_pass)
|
463
|
+
timeout = 0;
|
464
|
+
else if (timeout_ < 0)
|
465
|
+
timeout = -1;
|
466
|
+
else
|
467
|
+
timeout = end - now;
|
468
|
+
|
469
|
+
// Wait for events.
|
470
|
+
while (true) {
|
471
|
+
int rc = poll (pollfds, nitems_, timeout);
|
472
|
+
if (rc == -1 && errno == EINTR) {
|
473
|
+
free (pollfds);
|
474
|
+
return -1;
|
475
|
+
}
|
476
|
+
errno_assert (rc >= 0);
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
|
480
|
+
// Check for the events.
|
481
|
+
for (int i = 0; i != nitems_; i++) {
|
482
|
+
|
483
|
+
items_ [i].revents = 0;
|
484
|
+
|
485
|
+
// The poll item is a 0MQ socket. Retrieve pending events
|
486
|
+
// using the ZMQ_EVENTS socket option.
|
487
|
+
if (items_ [i].socket) {
|
488
|
+
size_t zmq_events_size = sizeof (uint32_t);
|
489
|
+
uint32_t zmq_events;
|
490
|
+
if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
|
491
|
+
&zmq_events_size) == -1) {
|
492
|
+
free (pollfds);
|
493
|
+
return -1;
|
494
|
+
}
|
495
|
+
if ((items_ [i].events & ZMQ_POLLOUT) &&
|
496
|
+
(zmq_events & ZMQ_POLLOUT))
|
497
|
+
items_ [i].revents |= ZMQ_POLLOUT;
|
498
|
+
if ((items_ [i].events & ZMQ_POLLIN) &&
|
499
|
+
(zmq_events & ZMQ_POLLIN))
|
500
|
+
items_ [i].revents |= ZMQ_POLLIN;
|
501
|
+
}
|
502
|
+
// Else, the poll item is a raw file descriptor, simply convert
|
503
|
+
// the events to zmq_pollitem_t-style format.
|
504
|
+
else {
|
505
|
+
if (pollfds [i].revents & POLLIN)
|
506
|
+
items_ [i].revents |= ZMQ_POLLIN;
|
507
|
+
if (pollfds [i].revents & POLLOUT)
|
508
|
+
items_ [i].revents |= ZMQ_POLLOUT;
|
509
|
+
if (pollfds [i].revents & ~(POLLIN | POLLOUT))
|
510
|
+
items_ [i].revents |= ZMQ_POLLERR;
|
511
|
+
}
|
512
|
+
|
513
|
+
if (items_ [i].revents)
|
514
|
+
nevents++;
|
515
|
+
}
|
516
|
+
|
517
|
+
// If timout is zero, exit immediately whether there are events or not.
|
518
|
+
if (timeout_ == 0)
|
519
|
+
break;
|
520
|
+
|
521
|
+
// If there are events to return, we can exit immediately.
|
522
|
+
if (nevents)
|
523
|
+
break;
|
524
|
+
|
525
|
+
// At this point we are meant to wait for events but there are none.
|
526
|
+
// If timeout is infinite we can just loop until we get some events.
|
527
|
+
if (timeout_ < 0) {
|
528
|
+
if (first_pass)
|
529
|
+
first_pass = false;
|
530
|
+
continue;
|
531
|
+
}
|
532
|
+
|
533
|
+
// The timeout is finite and there are no events. In the first pass
|
534
|
+
// we get a timestamp of when the polling have begun. (We assume that
|
535
|
+
// first pass have taken negligible time). We also compute the time
|
536
|
+
// when the polling should time out.
|
537
|
+
if (first_pass) {
|
538
|
+
now = clock.now_ms ();
|
539
|
+
end = now + (timeout_ / 1000);
|
540
|
+
if (now == end)
|
541
|
+
break;
|
542
|
+
first_pass = false;
|
543
|
+
continue;
|
544
|
+
}
|
545
|
+
|
546
|
+
// Find out whether timeout have expired.
|
547
|
+
now = clock.now_ms ();
|
548
|
+
if (now >= end)
|
549
|
+
break;
|
550
|
+
}
|
551
|
+
|
552
|
+
free (pollfds);
|
553
|
+
return nevents;
|
554
|
+
|
555
|
+
#elif defined ZMQ_POLL_BASED_ON_SELECT
|
556
|
+
|
557
|
+
if (unlikely (nitems_ < 0)) {
|
558
|
+
errno = EINVAL;
|
559
|
+
return -1;
|
560
|
+
}
|
561
|
+
if (unlikely (nitems_ == 0)) {
|
562
|
+
if (timeout_ == 0)
|
563
|
+
return 0;
|
564
|
+
#if defined ZMQ_HAVE_WINDOWS
|
565
|
+
Sleep (timeout_ > 0 ? timeout_ / 1000 : INFINITE);
|
566
|
+
return 0;
|
567
|
+
#else
|
568
|
+
return usleep (timeout_);
|
569
|
+
#endif
|
570
|
+
}
|
571
|
+
|
572
|
+
if (!items_) {
|
573
|
+
errno = EFAULT;
|
574
|
+
return -1;
|
575
|
+
}
|
576
|
+
|
577
|
+
zmq::clock_t clock;
|
578
|
+
uint64_t now = 0;
|
579
|
+
uint64_t end = 0;
|
580
|
+
|
581
|
+
// Ensure we do not attempt to select () on more than FD_SETSIZE
|
582
|
+
// file descriptors.
|
583
|
+
zmq_assert (nitems_ <= FD_SETSIZE);
|
584
|
+
|
585
|
+
fd_set pollset_in;
|
586
|
+
FD_ZERO (&pollset_in);
|
587
|
+
fd_set pollset_out;
|
588
|
+
FD_ZERO (&pollset_out);
|
589
|
+
fd_set pollset_err;
|
590
|
+
FD_ZERO (&pollset_err);
|
591
|
+
|
592
|
+
zmq::fd_t maxfd = 0;
|
593
|
+
|
594
|
+
// Build the fd_sets for passing to select ().
|
595
|
+
for (int i = 0; i != nitems_; i++) {
|
596
|
+
|
597
|
+
// If the poll item is a 0MQ socket we are interested in input on the
|
598
|
+
// notification file descriptor retrieved by the ZMQ_FD socket option.
|
599
|
+
if (items_ [i].socket) {
|
600
|
+
size_t zmq_fd_size = sizeof (zmq::fd_t);
|
601
|
+
zmq::fd_t notify_fd;
|
602
|
+
if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, ¬ify_fd,
|
603
|
+
&zmq_fd_size) == -1)
|
604
|
+
return -1;
|
605
|
+
if (items_ [i].events) {
|
606
|
+
FD_SET (notify_fd, &pollset_in);
|
607
|
+
if (maxfd < notify_fd)
|
608
|
+
maxfd = notify_fd;
|
609
|
+
}
|
610
|
+
}
|
611
|
+
// Else, the poll item is a raw file descriptor. Convert the poll item
|
612
|
+
// events to the appropriate fd_sets.
|
613
|
+
else {
|
614
|
+
if (items_ [i].events & ZMQ_POLLIN)
|
615
|
+
FD_SET (items_ [i].fd, &pollset_in);
|
616
|
+
if (items_ [i].events & ZMQ_POLLOUT)
|
617
|
+
FD_SET (items_ [i].fd, &pollset_out);
|
618
|
+
if (items_ [i].events & ZMQ_POLLERR)
|
619
|
+
FD_SET (items_ [i].fd, &pollset_err);
|
620
|
+
if (maxfd < items_ [i].fd)
|
621
|
+
maxfd = items_ [i].fd;
|
622
|
+
}
|
623
|
+
}
|
624
|
+
|
625
|
+
bool first_pass = true;
|
626
|
+
int nevents = 0;
|
627
|
+
fd_set inset, outset, errset;
|
628
|
+
|
629
|
+
while (true) {
|
630
|
+
|
631
|
+
// Compute the timeout for the subsequent poll.
|
632
|
+
timeval timeout;
|
633
|
+
timeval *ptimeout;
|
634
|
+
if (first_pass) {
|
635
|
+
timeout.tv_sec = 0;
|
636
|
+
timeout.tv_usec = 0;
|
637
|
+
ptimeout = &timeout;
|
638
|
+
}
|
639
|
+
else if (timeout_ < 0)
|
640
|
+
ptimeout = NULL;
|
641
|
+
else {
|
642
|
+
timeout.tv_sec = (long) ((end - now) / 1000);
|
643
|
+
timeout.tv_usec = (long) ((end - now) % 1000 * 1000);
|
644
|
+
ptimeout = &timeout;
|
645
|
+
}
|
646
|
+
|
647
|
+
// Wait for events. Ignore interrupts if there's infinite timeout.
|
648
|
+
while (true) {
|
649
|
+
memcpy (&inset, &pollset_in, sizeof (fd_set));
|
650
|
+
memcpy (&outset, &pollset_out, sizeof (fd_set));
|
651
|
+
memcpy (&errset, &pollset_err, sizeof (fd_set));
|
652
|
+
int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout);
|
653
|
+
#if defined ZMQ_HAVE_WINDOWS
|
654
|
+
wsa_assert (rc != SOCKET_ERROR);
|
655
|
+
#else
|
656
|
+
if (rc == -1 && errno == EINTR)
|
657
|
+
return -1;
|
658
|
+
errno_assert (rc >= 0);
|
659
|
+
#endif
|
660
|
+
break;
|
661
|
+
}
|
662
|
+
|
663
|
+
// Check for the events.
|
664
|
+
for (int i = 0; i != nitems_; i++) {
|
665
|
+
|
666
|
+
items_ [i].revents = 0;
|
667
|
+
|
668
|
+
// The poll item is a 0MQ socket. Retrieve pending events
|
669
|
+
// using the ZMQ_EVENTS socket option.
|
670
|
+
if (items_ [i].socket) {
|
671
|
+
size_t zmq_events_size = sizeof (uint32_t);
|
672
|
+
uint32_t zmq_events;
|
673
|
+
if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
|
674
|
+
&zmq_events_size) == -1)
|
675
|
+
return -1;
|
676
|
+
if ((items_ [i].events & ZMQ_POLLOUT) &&
|
677
|
+
(zmq_events & ZMQ_POLLOUT))
|
678
|
+
items_ [i].revents |= ZMQ_POLLOUT;
|
679
|
+
if ((items_ [i].events & ZMQ_POLLIN) &&
|
680
|
+
(zmq_events & ZMQ_POLLIN))
|
681
|
+
items_ [i].revents |= ZMQ_POLLIN;
|
682
|
+
}
|
683
|
+
// Else, the poll item is a raw file descriptor, simply convert
|
684
|
+
// the events to zmq_pollitem_t-style format.
|
685
|
+
else {
|
686
|
+
if (FD_ISSET (items_ [i].fd, &inset))
|
687
|
+
items_ [i].revents |= ZMQ_POLLIN;
|
688
|
+
if (FD_ISSET (items_ [i].fd, &outset))
|
689
|
+
items_ [i].revents |= ZMQ_POLLOUT;
|
690
|
+
if (FD_ISSET (items_ [i].fd, &errset))
|
691
|
+
items_ [i].revents |= ZMQ_POLLERR;
|
692
|
+
}
|
693
|
+
|
694
|
+
if (items_ [i].revents)
|
695
|
+
nevents++;
|
696
|
+
}
|
697
|
+
|
698
|
+
// If timout is zero, exit immediately whether there are events or not.
|
699
|
+
if (timeout_ == 0)
|
700
|
+
break;
|
701
|
+
|
702
|
+
// If there are events to return, we can exit immediately.
|
703
|
+
if (nevents)
|
704
|
+
break;
|
705
|
+
|
706
|
+
// At this point we are meant to wait for events but there are none.
|
707
|
+
// If timeout is infinite we can just loop until we get some events.
|
708
|
+
if (timeout_ < 0) {
|
709
|
+
if (first_pass)
|
710
|
+
first_pass = false;
|
711
|
+
continue;
|
712
|
+
}
|
713
|
+
|
714
|
+
// The timeout is finite and there are no events. In the first pass
|
715
|
+
// we get a timestamp of when the polling have begun. (We assume that
|
716
|
+
// first pass have taken negligible time). We also compute the time
|
717
|
+
// when the polling should time out.
|
718
|
+
if (first_pass) {
|
719
|
+
now = clock.now_ms ();
|
720
|
+
end = now + (timeout_ / 1000);
|
721
|
+
if (now == end)
|
722
|
+
break;
|
723
|
+
first_pass = false;
|
724
|
+
continue;
|
725
|
+
}
|
726
|
+
|
727
|
+
// Find out whether timeout have expired.
|
728
|
+
now = clock.now_ms ();
|
729
|
+
if (now >= end)
|
730
|
+
break;
|
731
|
+
}
|
732
|
+
|
733
|
+
return nevents;
|
734
|
+
|
735
|
+
#else
|
736
|
+
// Exotic platforms that support neither poll() nor select().
|
737
|
+
errno = ENOTSUP;
|
738
|
+
return -1;
|
739
|
+
#endif
|
740
|
+
}
|
741
|
+
|
742
|
+
#if defined ZMQ_POLL_BASED_ON_SELECT
|
743
|
+
#undef ZMQ_POLL_BASED_ON_SELECT
|
744
|
+
#endif
|
745
|
+
#if defined ZMQ_POLL_BASED_ON_POLL
|
746
|
+
#undef ZMQ_POLL_BASED_ON_POLL
|
747
|
+
#endif
|
748
|
+
|
749
|
+
int zmq_errno ()
|
750
|
+
{
|
751
|
+
return errno;
|
752
|
+
}
|
753
|
+
|
754
|
+
int zmq_device (int device_, void *insocket_, void *outsocket_)
|
755
|
+
{
|
756
|
+
if (!insocket_ || !outsocket_) {
|
757
|
+
errno = EFAULT;
|
758
|
+
return -1;
|
759
|
+
}
|
760
|
+
|
761
|
+
if (device_ != ZMQ_FORWARDER && device_ != ZMQ_QUEUE &&
|
762
|
+
device_ != ZMQ_STREAMER) {
|
763
|
+
errno = EINVAL;
|
764
|
+
return -1;
|
765
|
+
}
|
766
|
+
|
767
|
+
return zmq::device ((zmq::socket_base_t*) insocket_,
|
768
|
+
(zmq::socket_base_t*) outsocket_);
|
769
|
+
}
|
770
|
+
|
771
|
+
////////////////////////////////////////////////////////////////////////////////
|
772
|
+
// 0MQ utils - to be used by perf tests
|
773
|
+
////////////////////////////////////////////////////////////////////////////////
|
774
|
+
|
775
|
+
void zmq_sleep (int seconds_)
|
776
|
+
{
|
777
|
+
#if defined ZMQ_HAVE_WINDOWS
|
778
|
+
Sleep (seconds_ * 1000);
|
779
|
+
#else
|
780
|
+
sleep (seconds_);
|
781
|
+
#endif
|
782
|
+
}
|
783
|
+
|
784
|
+
void *zmq_stopwatch_start ()
|
785
|
+
{
|
786
|
+
uint64_t *watch = (uint64_t*) malloc (sizeof (uint64_t));
|
787
|
+
alloc_assert (watch);
|
788
|
+
*watch = zmq::clock_t::now_us ();
|
789
|
+
return (void*) watch;
|
790
|
+
}
|
791
|
+
|
792
|
+
unsigned long zmq_stopwatch_stop (void *watch_)
|
793
|
+
{
|
794
|
+
uint64_t end = zmq::clock_t::now_us ();
|
795
|
+
uint64_t start = *(uint64_t*) watch_;
|
796
|
+
free (watch_);
|
797
|
+
return (unsigned long) (end - start);
|
798
|
+
}
|