Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 381 lines (353 sloc) 11.846 kb
fa6cb33 @okeuday Add active receive with eunit tests. NIF code cleanup.
okeuday authored
1 %% -*- coding:utf-8;Mode:erlang;tab-width:4;c-basic-offset:4;indent-tabs-mode:nil -*-
2 %% ex: set softtabstop=4 tabstop=4 shiftwidth=4 expandtab fileencoding=utf-8:
3 %%
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
4 %% Copyright (c) 2011 Yurii Rashkovskii, Evax Software and Michael Truog
fa6cb33 @okeuday Add active receive with eunit tests. NIF code cleanup.
okeuday authored
5 %%
6 %% Permission is hereby granted, free of charge, to any person obtaining a copy
7 %% of this software and associated documentation files (the "Software"), to deal
8 %% in the Software without restriction, including without limitation the rights
9 %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 %% copies of the Software, and to permit persons to whom the Software is
11 %% furnished to do so, subject to the following conditions:
12 %%
13 %% The above copyright notice and this permission notice shall be included in
14 %% all copies or substantial portions of the Software.
15 %%
16 %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 %% THE SOFTWARE.
23
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
24 -module(erlzmq).
25 %% @headerfile "erlzmq.hrl"
26 -include_lib("erlzmq.hrl").
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
27 -export([context/0,
28 context/1,
29 socket/2,
30 bind/2,
31 connect/2,
32 send/2,
33 send/3,
34 recv/1,
35 recv/2,
36 setsockopt/3,
37 getsockopt/2,
38 close/1,
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
39 close/2,
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
40 term/1,
41 term/2]).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
42 -export_type([erlzmq_socket/0, erlzmq_context/0]).
43
44 %% @equiv context(1)
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
45 -spec context() ->
46 {ok, erlzmq_context()} |
47 erlzmq_error().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
48 context() ->
49 context(1).
50
51 %% @doc Create a new erlzmq context with the specified number of io threads.
52 %% <br />
53 %% If the context can be created an 'ok' tuple containing an
54 %% {@type erlzmq_context()} handle to the created context is returned;
55 %% if not, it returns an 'error' tuple with an {@type erlzmq_type_error()}
56 %% describing the error.
57 %% <br />
58 %% The context must be later cleaned up calling {@link erlzmq:term/1. term/1}
59 %% <br />
60 %% <i>For more information see
61 %% <a href="http://api.zeromq.org/master:zmq-init">zmq_init</a></i>
62 %% @end
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
63 -spec context(Threads :: pos_integer()) ->
64 {ok, erlzmq_context()} |
65 erlzmq_error().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
66 context(Threads) when is_integer(Threads) ->
67 erlzmq_nif:context(Threads).
68
69
70 %% @doc Create a socket.
71 %% <br />
72 %% This functions creates a socket of the given
26220ce @evax Minor doc update
evax authored
73 %% {@link erlzmq_socket_type(). type}, optionally setting it to active mode,
74 %% and associates it with the given {@link erlzmq_context(). context}.
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
75 %% <br />
76 %% If the socket can be created an 'ok' tuple containing a
77 %% {@type erlzmq_socket()} handle to the created socket is returned;
dad60ba @evax Document the performance implications of socket modes
evax authored
78 %% if not, it returns an {@type erlzmq_error()} describing the error.
79 %% <br />
80 %% In line with Erlang's socket paradigm, a socket can be either active or
81 %% passive. Passive sockets tend to have lower latency and have a higher
82 %% throughput for small message sizes. Active sockets on the contrary give
83 %% the highest throughput for messages above 32k. A benchmarking tool is
26220ce @evax Minor doc update
evax authored
84 %% included in the source distribution.<br />
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
85 %% <i>For more information see
86 %% <a href="http://api.zeromq.org/master:zmq_socket">zmq_socket</a>.</i>
87 %% @end
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
88 -spec socket(Context :: erlzmq_context(),
89 Type :: erlzmq_socket_type() |
90 list(erlzmq_socket_type() |
91 {active, boolean()})) ->
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
92 {ok, erlzmq_socket()} |
93 erlzmq_error().
fa6cb33 @okeuday Add active receive with eunit tests. NIF code cleanup.
okeuday authored
94 socket(Context, Type) when is_atom(Type) ->
95 socket(Context, [Type]);
96 socket(Context, [H | _] = L) ->
97 case lists:keytake(active, 1, L) of
98 {value, {active, Active}, [Type]} when Active =:= true ->
99 true = (Type =/= pub) and (Type =/= push) and (Type =/= xpub),
100 erlzmq_nif:socket(Context, socket_type(Type), 1);
101 {value, {active, Active}, [Type]} when Active =:= false ->
102 erlzmq_nif:socket(Context, socket_type(Type), 0);
103 false when H =:= pub; H =:= push; H =:= xpub ->
104 % active is not used for these socket types
105 erlzmq_nif:socket(Context, socket_type(H), 0);
106 false ->
78f5d0b @okeuday Make passive mode default.
okeuday authored
107 % active is false by default
108 % (to avoid latency on small messages (messages < 32KB))
109 erlzmq_nif:socket(Context, socket_type(H), 0)
fa6cb33 @okeuday Add active receive with eunit tests. NIF code cleanup.
okeuday authored
110 end.
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
111
112 %% @doc Accept connections on a socket.
113 %% <br />
114 %% <i>For more information see
115 %% <a href="http://api.zeromq.org/master:zmq_bind">zmq_bind</a>.</i>
116 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
117 -spec bind(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
118 Endpoint :: erlzmq_endpoint()) ->
119 ok |
120 erlzmq_error().
121 bind({I, Socket}, Endpoint)
122 when is_integer(I), is_list(Endpoint) ->
123 erlzmq_nif:bind(Socket, Endpoint).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
124
125 %% @doc Connect a socket.
126 %% <br />
127 %% <i>For more information see
128 %% <a href="http://api.zeromq.org/master:zmq_connect">zmq_connect</a>.</i>
129 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
130 -spec connect(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
131 Endpoint :: erlzmq_endpoint()) ->
132 ok |
133 erlzmq_error().
134 connect({I, Socket}, Endpoint)
135 when is_integer(I), is_list(Endpoint) ->
136 erlzmq_nif:connect(Socket, Endpoint).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
137
138 %% @equiv send(Socket, Msg, [])
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
139 -spec send(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
140 Data :: erlzmq_data()) ->
141 ok |
142 erlzmq_error().
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
143 send(Socket, Binary) when is_binary(Binary) ->
144 send(Socket, Binary, []).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
145
146 %% @doc Send a message on a socket.
147 %% <br />
148 %% <i>For more information see
149 %% <a href="http://api.zeromq.org/master:zmq_send">zmq_send</a>.</i>
150 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
151 -spec send(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
152 Data :: erlzmq_data(),
153 Flags :: erlzmq_send_recv_flags()) ->
154 ok |
155 erlzmq_error().
156 send({I, Socket}, Binary, Flags)
157 when is_integer(I), is_binary(Binary), is_list(Flags) ->
c459825 @evax Defer to polling thread on blocking send
evax authored
158 case erlzmq_nif:send(Socket, Binary, sendrecv_flags(Flags)) of
159 Ref when is_reference(Ref) ->
160 receive
161 {Ref, ok} ->
162 ok;
fa6cb33 @okeuday Add active receive with eunit tests. NIF code cleanup.
okeuday authored
163 {Ref, {error, _} = Error} ->
164 Error
c459825 @evax Defer to polling thread on blocking send
evax authored
165 end;
166 Result ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
167 Result
c459825 @evax Defer to polling thread on blocking send
evax authored
168 end.
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
169
170 %% @equiv recv(Socket, 0)
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
171 -spec recv(Socket :: erlzmq_socket()) ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
172 {ok, erlzmq_data()} |
173 erlzmq_error().
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
174 recv(Socket) ->
175 recv(Socket, []).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
176
177 %% @doc Receive a message from a socket.
178 %% <br />
179 %% <i>For more information see
180 %% <a href="http://api.zeromq.org/master:zmq_recv">zmq_recv</a>.</i>
181 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
182 -spec recv(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
183 Flags :: erlzmq_send_recv_flags()) ->
184 {ok, erlzmq_data()} |
185 erlzmq_error() |
186 {error, {timeout, reference()}}.
187 recv({I, Socket}, Flags)
188 when is_integer(I), is_list(Flags) ->
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
189 case erlzmq_nif:recv(Socket, sendrecv_flags(Flags)) of
190 Ref when is_reference(Ref) ->
191 Timeout = proplists:get_value(timeout, Flags, infinity),
192 receive
6cf222c @ianbarber Changing the recv() back to a 2-tuple response
ianbarber authored
193 {Ref, Result} ->
194 {ok, Result}
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
195 after Timeout ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
196 {error, {timeout, Ref}}
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
197 end;
198 Result ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
199 Result
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
200 end.
201
202 %% @doc Set an {@link erlzmq_sockopt(). option} associated with a socket.
203 %% <br />
204 %% <i>For more information see
205 %% <a href="http://api.zeromq.org/master:zmq_setsockopt">zmq_setsockopt</a>.</i>
206 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
207 -spec setsockopt(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
208 Name :: erlzmq_sockopt(),
209 erlzmq_sockopt_value()) ->
210 ok |
211 erlzmq_error().
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
212 setsockopt(Socket, Name, Value) when is_list(Value) ->
213 setsockopt(Socket, Name, erlang:list_to_binary(Value));
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
214 setsockopt({I, Socket}, Name, Value) when is_integer(I), is_atom(Name) ->
215 erlzmq_nif:setsockopt(Socket, option_name(Name), Value).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
216
217 %% @doc Get an {@link erlzmq_sockopt(). option} associated with a socket.
218 %% <br />
219 %% <i>For more information see
220 %% <a href="http://api.zeromq.org/master:zmq_getsockopt">zmq_getsockopt</a>.</i>
221 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
222 -spec getsockopt(Socket :: erlzmq_socket(),
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
223 Name :: erlzmq_sockopt()) ->
224 {ok, erlzmq_sockopt_value()} |
225 erlzmq_error().
226 getsockopt({I, Socket}, Name) when is_integer(I), is_atom(Name) ->
227 erlzmq_nif:getsockopt(Socket, option_name(Name)).
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
228
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
229 %% @equiv close(Socket, infinity)
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
230 -spec close(Socket :: erlzmq_socket()) ->
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
231 ok |
232 erlzmq_error().
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
233 close(Socket) ->
234 close(Socket, infinity).
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
235
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
236 %% @doc Close the given socket.
237 %% <br />
238 %% <i>For more information see
239 %% <a href="http://api.zeromq.org/master:zmq_close">zmq_close</a>.</i>
240 %% @end
32a7039 @yrashk Simplify use of erlzmq_socket() type
yrashk authored
241 -spec close(Socket :: erlzmq_socket(),
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
242 Timeout :: timeout()) ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
243 ok |
244 erlzmq_error().
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
245 close({I, Socket}, Timeout) when is_integer(I) ->
246 case erlzmq_nif:close(Socket) of
247 Ref when is_reference(Ref) ->
248 receive
249 {Ref, Result} ->
250 Result
251 after
252 Timeout ->
253 {error, {timeout, Ref}}
254 end;
255 Result ->
256 Result
257 end.
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
258
259 %% @equiv term(Context, infinity)
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
260 -spec term(Context :: erlzmq_context()) ->
261 ok |
262 erlzmq_error().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
263 term(Context) ->
264 term(Context, infinity).
265
266 %% @doc Terminate the given context waiting up to Timeout ms.
267 %% <br />
268 %% This function should be called after all sockets associated with
269 %% the given context have been closed.<br />
270 %% If not it will block the given Timeout amount of time.
271 %% <i>For more information see
272 %% <a href="http://api.zeromq.org/master:zmq_term">zmq_term</a>.</i>
273 %% @end
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
274 -spec term(Context :: erlzmq_context(),
275 Timeout :: timeout()) ->
276 ok |
277 erlzmq_error() |
278 {error, {timeout, reference()}}.
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
279
280 term(Context, Timeout) ->
281 case erlzmq_nif:term(Context) of
282 Ref when is_reference(Ref) ->
283 receive
284 {Ref, Result} ->
285 Result
91b4e62 @okeuday Make the NIF more robust. Guard non-reentrant ZeroMQ sockets. Provide ...
okeuday authored
286 after
287 Timeout ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
288 {error, {timeout, Ref}}
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
289 end;
290 Result ->
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
291 Result
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
292 end.
293
294
295 %% Private
296
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
297 -spec socket_type(Type :: erlzmq_socket_type()) ->
298 integer().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
299
300 socket_type(pair) ->
301 ?'ZMQ_PAIR';
302 socket_type(pub) ->
303 ?'ZMQ_PUB';
304 socket_type(sub) ->
305 ?'ZMQ_SUB';
306 socket_type(req) ->
307 ?'ZMQ_REQ';
308 socket_type(rep) ->
309 ?'ZMQ_REP';
e7464db @gar1t dealer and router socket types
gar1t authored
310 socket_type(dealer) ->
311 ?'ZMQ_DEALER';
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
312 socket_type(xreq) ->
313 ?'ZMQ_XREQ';
e7464db @gar1t dealer and router socket types
gar1t authored
314 socket_type(router) ->
315 ?'ZMQ_ROUTER';
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
316 socket_type(xrep) ->
317 ?'ZMQ_XREP';
318 socket_type(pull) ->
319 ?'ZMQ_PULL';
320 socket_type(push) ->
321 ?'ZMQ_PUSH';
322 socket_type(xpub) ->
323 ?'ZMQ_XPUB';
324 socket_type(xsub) ->
325 ?'ZMQ_XSUB'.
326
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
327 -spec sendrecv_flags(Flags :: erlzmq_send_recv_flags()) ->
328 integer().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
329
330 sendrecv_flags([]) ->
331 0;
332 sendrecv_flags([{timeout,_}]) ->
333 0;
334 sendrecv_flags([noblock|Rest]) ->
335 ?'ZMQ_NOBLOCK' bor sendrecv_flags(Rest);
336 sendrecv_flags([sndmore|Rest]) ->
337 ?'ZMQ_SNDMORE' bor sendrecv_flags(Rest).
338
9ed06d9 @okeuday Provide a 2tuple/index envelope for matching on erlzmq sockets returned ...
okeuday authored
339 -spec option_name(Name :: erlzmq_sockopt()) ->
340 integer().
baa8345 @yrashk Renamed ezmq to erlzmq2
yrashk authored
341
342 option_name(hwm) ->
343 ?'ZMQ_HWM';
344 option_name(swap) ->
345 ?'ZMQ_SWAP';
346 option_name(affinity) ->
347 ?'ZMQ_AFFINITY';
348 option_name(identity) ->
349 ?'ZMQ_IDENTITY';
350 option_name(subscribe) ->
351 ?'ZMQ_SUBSCRIBE';
352 option_name(unsubscribe) ->
353 ?'ZMQ_UNSUBSCRIBE';
354 option_name(rate) ->
355 ?'ZMQ_RATE';
356 option_name(recovery_ivl) ->
357 ?'ZMQ_RECOVERY_IVL';
358 option_name(mcast_loop) ->
359 ?'ZMQ_MCAST_LOOP';
360 option_name(sndbuf) ->
361 ?'ZMQ_SNDBUF';
362 option_name(rcvbuf) ->
363 ?'ZMQ_RCVBUF';
364 option_name(rcvmore) ->
365 ?'ZMQ_RCVMORE';
366 option_name(fd) ->
367 ?'ZMQ_FD';
368 option_name(events) ->
369 ?'ZMQ_EVENTS';
370 option_name(linger) ->
371 ?'ZMQ_LINGER';
372 option_name(reconnect_ivl) ->
373 ?'ZMQ_RECONNECT_IVL';
374 option_name(backlog) ->
375 ?'ZMQ_BACKLOG';
376 option_name(recovery_ivl_msec) ->
377 ?'ZMQ_RECOVERY_IVL_MSEC';
378 option_name(reconnect_ivl_max) ->
379 ?'ZMQ_RECONNECT_IVL_MAX'.
380
Something went wrong with that request. Please try again.