I have never used ZeroMQ and first heard of it an hour ago. But from the guide (this guide) it sounds like there are async I/O.

It also happens that there is a nim port : this one

So I was wondering, does the async magic has something to do with async/await which are keywords not present in the nim port (which is just c2nim). So is it just something that's internal to ZMQ and the API doesn't have to bother about it ?

I thought async/await was a vernacular thing that has to bubble up to the upper most main loop (framework loop) so the API would have to be async-aware.

Is this a complete misconception on my part ?


Solution 1:

Native ZeroMQ API supports both blocking and non-blocking I/O-s.

For this purpose, there are flags, where zmq.NOBLOCK could be added, so as to achieve a non-blocking mode of operation.


The respective language-wrapper functionality decides . . .

If I read the nim ZeroMQ-wrapper, that you have mentioned above, it seems to me, that there is a hardcoded blocking version for both send() and recv() function-wrappers.

The wrapper also seems not to support correct wireline message sizing in case a nim-based node of a distributed-system meets another node, which is using ZeroMQ version 2.1.+, which is still interesting and common in heterogeneous distributed-system realms.

ZeroMQ has also a poll() method, equipped with a timeout parameter, so that your multiplexed I/O-operations may yield all wanted ways of how to operate multiple I/O-channels under some soft real-time control constraints.

Solution 2:

While the accepted answer was true at the time; async with ZMQ now is built with the wrapper and there are examples provided :

See :

  • https://github.com/nim-lang/nim-zmq/blob/master/zmq/asynczmq.nim
  • https://github.com/nim-lang/nim-zmq/blob/master/examples/ex08_async_reqrep.nim

You can also work around the blocking behaviour or ZMQ in order to not block the async-dispatch loop manually with poll / sleepAsync :

let
  zmq_timeout = 50
  async_loop_time = 450 # spend more time on async stuff than on zmq stuff
var
  conn = listen("tcp://127.0.0.1:36000", mode = PAIR=
  poller = initZPoll([conn], ZMQ_POLLIN)

if poller.poll(timeout):
  if events(poller[0]):
    var res = poller[0].receive()
    # Do async stuff
else:
  waitFor sleepAsync(async_loop_time) # Calling sleepAsync is a trick to make the async dispatch loop progress for a time