4 releases (breaking)
0.4.0 | Sep 10, 2024 |
---|---|
0.3.0 | Feb 20, 2024 |
0.2.1 |
|
0.2.0 | Jan 28, 2024 |
0.1.0 | Oct 3, 2023 |
#1071 in Concurrency
216 downloads per month
Used in umpx
18KB
219 lines
Server message dispatch loop for ump
The ump-server crate is a server message dispatch abstraction for ump.
lib.rs
:
ump-server is an abstraction on top of [ump
] that is used to hide
boilerplate code used to implement intra-process message passing servers.
Dispatch loop
The core functionality of ump-server is a dispatch loop, whose role it is to pull messages off the message queue and pass them to the application-supplied message handler.
There are two different ways to run the dispatcher loop: On a non-async
thread or as an async task. The former is launched using
[thread::spawn()
] and the latter [task::spawn()
] (only available using
the tokio
feature).
The spawn()
functions return a tuple containing a Client
(that can be
used to send pass messages to the server) and a JoinHandle
that can be
used to wait for the dispatch loop thread/task to terminate (and retreive
its return value).
The returned JoinHandle
will, once joined, return an Option<RV>
.
If this is None
the server was terminated because all the Client
endpoints were dropped. If this is Some(RV)
the server was terminated
because a callback requested its termination by returning
ControlFlow::Break(RV)
.
There are two ways to terminate the dispatch loop:
- The message processing handler returns
ControlFlow::Break(RV)
(rather thanControlFlow::Continue(())
). This would cause the thread/task to returnSome(RV)
. - The message queue is empty and all the associated
Client
s have been released. This would cause the thread to returnNone
.
Application message handlers
Message handlers are implemented using the thread::Handler
trait (for
the threaded dispatch loop) and task::Handler
(for the async dispatch
loop).
There are cases where the handler needs to store a clone of the client
end-point of the message passing channel used to issue requests to the
server (so that message handlers can issue new requests). In order to
facilitate this, the application must pass a Handler
-construction closure
to spawn()
. The closure will be called after the message passing channel
has been created so it can be passed a reference to the client end-point.
If the dispatch loop should terminate once all the application's client
end-points have been dropped, then the handler can store a WeakClient
instead (as storing a cloned Client
object will preventing the dispatch
loop from terminating due to all clients being lost). The examples in the
task
and thread
modules illustrate how to do this.
Dependencies
~3–9MB
~76K SLoC