@@ -94,3 +94,94 @@ impl SocketSend for DealerSocket {
9494}
9595
9696impl CaptureSocket for DealerSocket { }
97+
98+ impl DealerSocket {
99+ /// Splits the socket into separate send and recv halves, allowing concurrent
100+ /// sending and receiving from independent async tasks.
101+ ///
102+ /// The underlying socket stays alive until both halves are dropped.
103+ pub fn split ( mut self ) -> ( DealerSendHalf , DealerRecvHalf ) {
104+ // Swap the real fields out before self drops. The dummy backend's
105+ // shutdown() is a no-op on an empty peer map.
106+ let backend = std:: mem:: replace (
107+ & mut self . backend ,
108+ Arc :: new ( GenericSocketBackend :: with_options (
109+ None ,
110+ SocketType :: DEALER ,
111+ SocketOptions :: default ( ) ,
112+ ) ) ,
113+ ) ;
114+ let fair_queue = std:: mem:: replace ( & mut self . fair_queue , FairQueue :: new ( true ) ) ;
115+ let binds = std:: mem:: take ( & mut self . binds ) ;
116+
117+ let inner = Arc :: new ( DealerSocketInner {
118+ backend,
119+ _binds : binds,
120+ } ) ;
121+
122+ (
123+ DealerSendHalf {
124+ inner : inner. clone ( ) ,
125+ } ,
126+ DealerRecvHalf {
127+ _inner : inner,
128+ fair_queue,
129+ } ,
130+ )
131+ }
132+ }
133+
134+ struct DealerSocketInner {
135+ backend : Arc < GenericSocketBackend > ,
136+ _binds : HashMap < Endpoint , AcceptStopHandle > ,
137+ }
138+
139+ impl Drop for DealerSocketInner {
140+ fn drop ( & mut self ) {
141+ self . backend . shutdown ( ) ;
142+ }
143+ }
144+
145+ /// The send half of a [`DealerSocket`] produced by [`DealerSocket::split`].
146+ pub struct DealerSendHalf {
147+ inner : Arc < DealerSocketInner > ,
148+ }
149+
150+ /// The recv half of a [`DealerSocket`] produced by [`DealerSocket::split`].
151+ pub struct DealerRecvHalf {
152+ _inner : Arc < DealerSocketInner > ,
153+ fair_queue : FairQueue < ZmqFramedRead , PeerIdentity > ,
154+ }
155+
156+ #[ async_trait]
157+ impl SocketSend for DealerSendHalf {
158+ async fn send ( & mut self , message : ZmqMessage ) -> ZmqResult < ( ) > {
159+ self . inner
160+ . backend
161+ . send_round_robin ( Message :: Message ( message) )
162+ . await ?;
163+ Ok ( ( ) )
164+ }
165+ }
166+
167+ impl CaptureSocket for DealerSendHalf { }
168+
169+ #[ async_trait]
170+ impl SocketRecv for DealerRecvHalf {
171+ async fn recv ( & mut self ) -> ZmqResult < ZmqMessage > {
172+ loop {
173+ match self . fair_queue . next ( ) . await {
174+ Some ( ( _peer_id, Ok ( Message :: Message ( message) ) ) ) => {
175+ return Ok ( message) ;
176+ }
177+ Some ( ( _peer_id, Ok ( _) ) ) => { }
178+ Some ( ( _peer_id, Err ( e) ) ) => {
179+ return Err ( e. into ( ) ) ;
180+ }
181+ None => {
182+ return Err ( ZmqError :: NoMessage ) ;
183+ }
184+ } ;
185+ }
186+ }
187+ }
0 commit comments