@@ -90,17 +90,7 @@ proc pollAsync*(poller: AsyncZPoller, timeout: int = 2) : Future[int] =
9090
9191 result .complete (r)
9292
93- proc receiveAsync * (conn: ZConnection ): Future [string ] =
94- # # Similar to `receive()`, but `receiveAsync()` allows other async tasks to run.
95- # # `receiveAsync()` allows other async tasks to run in those cases.
96- # #
97- # # This will not work in some case because it depends on ZMQ_FD which is not necessarily the 'true' FD of the socket
98- # #
99- # # See https://github.com/zeromq/libzmq/issues/2941 and https://github.com/zeromq/pyzmq/issues/1411
100- let fut = newFuture [string ](" receiveAsync" )
101- result = fut
102- let sock = conn.socket
103-
93+ template receiveAsyncCallbackTemplate (fut: Future , sock: ZSocket , recv, cb) =
10494 proc cb (fd: AsyncFD ): bool {.closure , gcsafe .} =
10595 # the cb should work on the low level socket and not the ZConnection object
10696 result = true
@@ -116,15 +106,45 @@ proc receiveAsync*(conn: ZConnection): Future[string] =
116106 else :
117107 # ready to read
118108 unregister (fd)
119- fut.complete sock. receive ( DONTWAIT )
109+ fut.complete recv (sock, DONTWAIT )
120110 except :
121111 unregister (fd)
122112 fut.fail getCurrentException ()
123113
114+ proc receiveAsync * (conn: ZConnection ): Future [string ] =
115+ # # Similar to `receive()`, but `receiveAsync()` allows other async tasks to run.
116+ # # `receiveAsync()` allows other async tasks to run in those cases.
117+ # #
118+ # # This will not work in some case because it depends on ZMQ_FD which is not necessarily the 'true' FD of the socket
119+ # #
120+ # # See https://github.com/zeromq/libzmq/issues/2941 and https://github.com/zeromq/pyzmq/issues/1411
121+ let fut = newFuture [string ](" receiveAsync" )
122+ result = fut
123+ receiveAsyncCallbackTemplate (fut, conn.socket, receive, cb)
124124 let fd = getsockopt [cint ](conn, ZSockOptions .FD ).AsyncFD
125125 register (fd)
126126 discard cb (fd)
127127
128+ proc tryReceiveAsync * (conn: ZConnection ): Future [tuple [msgAvailable: bool , moreAvailable: bool , msg: string ]] =
129+ # # Async version of `tryReceive()`
130+ let fut = newFuture [tuple [msgAvailable: bool , moreAvailable: bool , msg: string ]](" tryReceiveAsync" )
131+ result = fut
132+ receiveAsyncCallbackTemplate (fut, conn.socket, tryReceive, cb)
133+ let fd = getsockopt [cint ](conn, ZSockOptions .FD ).AsyncFD
134+ register (fd)
135+ discard cb (fd)
136+
137+ proc receiveAllAsync * (conn: ZConnection ): Future [seq [string ]] {.async .} =
138+ # # async version for `receiveAll()`
139+ var expectMessage = true
140+ while expectMessage:
141+ let (msgAvailable, moreAvailable, msg) = await tryReceiveAsync (conn)
142+ if msgAvailable:
143+ result .add msg
144+ expectMessage = moreAvailable
145+ else :
146+ expectMessage = false
147+
128148proc sendAsync * (conn: ZConnection , msg: string , flags: ZSendRecvOptions = DONTWAIT ): Future [void ] =
129149 # # `send()` is blocking for some connection types (e.g. PUSH, DEALER).
130150 # # `sendAsync()` allows other async tasks to run in those cases.
@@ -134,11 +154,11 @@ proc sendAsync*(conn: ZConnection, msg: string, flags: ZSendRecvOptions = DONTWA
134154 # # See https://github.com/zeromq/libzmq/issues/2941 and https://github.com/zeromq/pyzmq/issues/1411
135155 let fut = newFuture [void ](" sendAsync" )
136156 result = fut
137- let sock = conn.socket
138157
139158 let status = getsockopt [cint ](conn, ZSockOptions .EVENTS )
140159 if (status and ZMQ_POLLOUT ) == 0 :
141160 # wait until queue available
161+ let sock = conn.socket
142162 proc cb (fd: AsyncFD ): bool {.closure , gcsafe .} =
143163 result = true
144164
0 commit comments