|
|
|
|
|
by ninkendo
424 days ago
|
|
Same. It’s a pattern I’m reaching for a lot, whenever I have multiple logical things that need to run concurrently. Generally: - A struct that represents the mutable state I’m wrapping - A start(self) method which moves self to a tokio task running a loop reading from an mpsc::Receiver<Command> channel, and returns a Handle object which is cloneable and contains the mpsc::Sender end - The handle can be used to send commands/requests (including one shot channels for replies) - When the last handle is dropped, the mpsc channel is dropped and the loop ends It basically lets me think of each logical concurrent service as being like a tcp server that accepts requests. They can call each other by holding instances of the Handle type and awaiting calls (this can still deadlock if there’s a call cycle and the handling code isn’t put on a background task… in practice I’ve never made this mistake though) Some day I’ll maybe start using an actor framework (like Axum/etc) which formalizes this a bit more, but for now just making these types manually is simple enough. |
|