5 releases
Uses old Rust 2015
0.1.0 | Oct 10, 2017 |
---|---|
0.0.4 | Apr 26, 2017 |
0.0.3 | Apr 26, 2017 |
0.0.2 | Apr 25, 2017 |
0.0.1 | Apr 25, 2017 |
#759 in Concurrency
6,117 downloads per month
9KB
61 lines
swapper
Swap ownership of data between threads in Rust.
This crate allows threads to swap ownership of data without a transitory state where the thread owns nothing.
let (ab, ba) = swapper::swapper();
thread::spawn(move || {
let mut a = String::from("hello");
ab.swap(&mut a).unwrap();
assert_eq!(a, "world");
});
let mut b = String::from("world");
ba.swap(&mut b).unwrap();
assert_eq!(b, "hello");
lib.rs
:
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(),
}
}
}