reqchan-rs
defines a channel for requesting and receiving data.
Introduction
Each channel has only one requesting end, but it can have multiple responding ends. It is useful for implementing work sharing.
The two ends of the channel are asynchronous with respect to each other, so it is kinda nonblocking. However, if multiple responding ends try to respond to the same request, only one will succeed; the rest will return errors.
Design
Overview
reqchan
is built around the two halves of the channel: Requester
and Responder
. Both implement methods, Requester::try_request()
and Responder::try_respond()
, that, when succesful, lock their corresponding side of the channel and return contracts. RequestContract
requires the user to either successfully receive a datum or cancel the request. ResponseContract
requires the user to send a datum. These requirements prevent the system from losing data sent through the channel.
Locking
Responder::try_response()
locks the responding side to prevent other potential responders from responding to the same request. However, Requester::try_request()
locks the requesting side of the channel to prevent the user from trying to issue multiple outstanding requests. Both locks are dropped when their corresponding contract object is dropped.
Contracts
Requester::try_request()
has to issue a RequestContract
so the thread of execution does not block waiting for a response. However, that reason does not apply to Responder::try_response()
. I originally made Responder::try_response()
send the datum. However, that required the user to have the datum available to send even if it could not be sent, and it required the user to handle the returned datum if it could not be sent. If the datum was, say, half the contents of a Vec
, this might entail lots of expensive memory allocation. Therefore, I made Responder::try_response()
return a ResponseContract
indicating that the responder could and would respond to the request. This way the user only has to perform the necessary steps to send the datum if the datum must be sent.
Examples
Simple Example
This simple, single-threaded example demonstrates most of the API. The only thing left out is RequestContract::try_cancel()
.
extern crate reqchan;
More Complex Example
This more complex example demonstrates more "real-world" usage. One thread requests a 'task' (i.e. a closure to run), and the other two threads fight over who gets to respond with their own personal task. Meanwhile, the requesting thread is polling for a task, and if it gets one in time, it runs it. Regardless of whether or not the receiver got a task or timed out, the receiver notifies other threads to stop running, and stops itself.
extern crate reqchan as chan;
use Arc;
use ;
use thread;
use ;
// Stuff to make it easier to pass around closures.
type Task = ;
Platforms
reqchan-rs
should Work on Windows and any POSIX compatible system (Linux, Mac OSX, etc.).
reqchan-rs
is continuously tested on:
x86_64-unknown-linux-gnu
(Linux)i686-unknown-linux-gnu
x86_64-unknown-linux-musl
(Linux w/ MUSL)i686-unknown-linux-musl
x86_64-apple-darwin
(Mac OSX)i686-apple-darwin
x86_64-pc-windows-msvc
(Windows)i686-pc-windows-msvc
x86_64-pc-windows-gnu
i686-pc-windows-gnu
reqchan-rs
is continuously cross-compiled for:
arm-unknown-linux-gnueabihf
aarch64-unknown-linux-gnu
mips-unknown-linux-gnu
aarch64-unknown-linux-musl
i686-linux-android
x86_64-linux-android
arm-linux-androideabi
aarch64-linux-android
i386-apple-ios
x86_64-apple-ios
i686-unknown-freebsd
x86_64-unknown-freebsd
x86_64-unknown-netbsd
asmjs-unknown-emscripten