ZMQ4L
December 13, 2013 ยท View on GitHub
This is "yet another wrapper" for ZMQ. This utilizes autowrap and wraps version 4.0.1 as of writing.
This is a nearly-complete wrap, excepting the following:
- Functions documented as deprecated (
zmq_init(),zmq_recvmsg(), etc) zmq_send_const()which is not particularly useful in the context of CL
As of writing you will need the latest version of autowrap from the repository.
API
Overview
The API coverage is similar to the ZMQ C API such that the C
documentation should translate fairly directly. Functions are
exported from the ZMQ4 package and do not have a ZMQ- prefix.
For instance, zmq_ctx_new() is now zmq4:ctx-new, etc.
Exceptions:
zmq_close()->zmq4:close-socket: To avoid shadowingCL:CLOSE.zmq4:msg-initcreates a message, in addition to initializing
As per normal autowrap, shortest-suffix keywords may be used instead of numeric constants for enums and masks. For instance:
;; Masks use a list of keywords:
(zmq4:send SOCK DATA '(:dontwait))
(zmq4:send SOCK DATA '(:dontwait :sndmore))
;; Enums use a lone keyword:
(zmq4:getsockopt SOCK :type)
POLL
Poll is perhaps of particular note since it's a bit more complex than the rest of the API.
(let ((pollitem (zmq4:make-pollitem (list sock1 :in)
(list sock2 :out ...))))
(poll pollitem TIMEOUT))
;; May return something like:
;; ((#<SOCKET ...> :IN) ...)
Sockets in this case can be ZMQ-SOCKET or integer file descriptors.
This may be a bit wordy, so provided are the following macros:
(zmq4:do-poll (sock events &optional TIMEOUT)
((sock1 :in)
(sock2 :in :out :err))
END-TEST-FORM
body...)
This will loop and interate over each socket with events. It finishes
when END-TEST-FORM evaluates to a non-NIL value, or TIMEOUT is
reached without any events. In this case, sock and events will be
assigned to, for instance, the value of sock1 and (:in),
respectively.
Note that END-TEST-FORM is only evaluated between calls to
zmq_poll(), so more sockets may be iterated before the loop quits.
Alternatively, there is DO-POLLITEM, which provides a slightly more
robust loop:
(zmq4:do-pollitem (sock events &optional TIMEOUT)
POLLITEM-FORM
END-TEST-FORM
body...)
In this case, POLLITEM-FORM is a pollitem created by make-pollitem, and
is evaluated every iteration before zmq_poll(). Thus, you may use
a variable and reassign it to a new pollitem, if for instance you wish
to remove or add sockets. Otherwise, the semantics are the same.
STATIC-VECTORS
If desired, ZMQ4L supports
static-vectors. To
use, you may load the system :zmq4l-with-sv, which will load ZMQ4L,
static-vectors, and the appropriate additional definitions.
The following functions are added:
send-sv SOCKET STATIC-VECTOR &optional FLAGS: Likesend, but the contents are pulled directly fromSTATIC-VECTOR. You must still manage the static vector. This is likely considerably faster thansend, because the contents are not copied byte-by-byte from a lisp array to foreign.recv-sv SOCKET STATIC-VECTOR &optional FLAGS: Likerecv, but the contents are written directly toSTATIC-VECTOR. You must still manage the static vector. This is likely considerably faster thansend, because the contents are not copied byte-by-byte from a foreign array to lisp.msg-init-sv STATIC-VECTOR: Likemsg-initwith a standard array, except this usesmemcpy()rather than a slower byte-by-byte copy from lisp to a foreign array. You must still manage the static vector.msg-init-data STATIC-VECTOR &optional FREE-FUN: Create a message, using the data inSTATIC-VECTORdirectly. By default,FREE-FUNisfree-static-vector, which will free the static vector. This means that afterMSG-CLOSEorMSG-SEND, the static-vector must not be accessed further, because it may be freed immediately. Caveats apply, see below.
These functions will not be defined if :zmq4l-with-sv is not loaded,
but the symbols will be exported.
Caveats: The use of msg-init-data requires lisp functions be
callable in arbitrary foreign threads, including those your lisp may
not know about. By default, SBCL does not support this except on
Windows. CCL does support this. I am not sure of the status of other
lisps; use at your own discretion.
For SBCL, you may build with the options --with-sb-safepoint --with-sb-thruption --with-sb-wtimer to enable foreign thread
callbacks. This is reportedly safe on Linux x86_64.
send-sv, recv-sv, and msg-init-sv are safe regardless.