Crate swapper [−] [src]
Concurrency control for atomic swap of ownership.
A common pattern for thread pools is that each thread owns a token, and some times threads need to exchange tokens. A skeleton example is:
struct Token; enum Message { // Messages go here }; struct Thread { sender_to_other_thread: Sender<Message>, receiver_from_other_thread: Receiver<Message>, token: Token, } impl Thread { fn swap_token(&mut self) { // This function should swap the token with the other thread. } fn handle(&mut self, message: Message) { match message { // Message handlers go here } } fn run(&mut self) { loop { let message = self.receiver_from_other_thread.recv(); match message { Ok(message) => self.handle(message), Err(_) => return, } } } }
To do this with the Rust channels, ownership of the token is first
passed from the thread to the channel, then to the other thead,
resulting in a transitory state where the thread does not have the
token. Typically to work round this, the thread stores an Option<Token>
rather than a Token
:
enum Message { SwapToken(Token, Sender<Token>), }; struct Thread { sender_to_other_thread: Sender<Message>, receiver_from_other_thread: Receiver<Message>, token: Option<Token>, // ANNOYING Option } impl Thread { fn swap_token(&mut self) { let (sender, receiver) = mpsc::channel(); let token = self.token.take().unwrap(); self.sender_to_other_thread.send(Message::SwapToken(token, sender)); let token = receiver.recv().unwrap(); self.token = Some(token); } fn handle(&mut self, message: Message) { match message { Message::SwapToken(token, sender) => { let token = mem::replace(&mut self.token, Some(token)).unwrap(); sender.send(token).unwrap(); } } } }
This crate provides a synchronization primitive for swapping ownership between threads.
The API is similar to channels, except that rather than separate send(T)
and recv():T
methods, there is one swap(T):T
, which swaps a T
owned by one thread for a T
owned
by the other. For example, it allows an implementation of the thread pool which always
owns a token.
enum Message { SwapToken(Swapper<Token>), }; struct Thread { sender_to_other_thread: Sender<Message>, receiver_from_other_thread: Receiver<Message>, token: Token, } impl Thread { fn swap_token(&mut self) { let (our_swapper, their_swapper) = swapper::swapper(); self.sender_to_other_thread.send(Message::SwapToken(their_swapper)); our_swapper.swap(&mut self.token).unwrap(); } fn handle(&mut self, message: Message) { match message { Message::SwapToken(swapper) => swapper.swap(&mut self.token).unwrap(), } } }
Structs
SwapError |
The error returned when a thread attempts to swap with a thread that has dropped its swapper. |
Swapper |
A concurrency control for swapping ownership between threads. |
Functions
swapper |
Create a new pair of swappers. |