Skip to content

Instantly share code, notes, and snippets.

@jorendorff
Last active November 15, 2016 03:58
Show Gist options
  • Save jorendorff/17b68de490d4ee5b47cd07a2826a8ce2 to your computer and use it in GitHub Desktop.
Save jorendorff/17b68de490d4ee5b47cd07a2826a8ce2 to your computer and use it in GitHub Desktop.
//! Some generic code for launching a service.
use std::sync::mpsc::{Sender, channel};
use std::thread::{spawn, JoinHandle};
/// Wrapper around a JoinHandle that automatically joins when dropped.
struct AutoJoinHandle(Option<JoinHandle<()>>);
impl Drop for AutoJoinHandle {
fn drop(&mut self) {
if let Some(thread) = self.0.take() {
thread.join().unwrap();
}
}
}
/// A running Service.
///
/// Note: Currently you can send a `Service<R>` value to another thread,
/// but you can't share it across many threads at once, a dumb restriction.
pub struct Service<Request>
{
sender: Sender<Request>,
#[allow(dead_code)] // this is here for its behavior on drop
thread: AutoJoinHandle
}
impl<Request> Service<Request>
where Request: Send + 'static
{
/// Launch a service.
///
/// To stop the service, just drop the value.
///
pub fn new<F>(mut f: F) -> Service<Request>
// Rules about what `f` must be. It must be a closure ... that takes a
// single `Request` argument ... that can be sent to another thread.
where F: FnMut(Request) + Send + 'static
{
let (sender, receiver) = channel();
let thread = spawn(move || {
for request in receiver {
f(request);
}
});
Service {
thread: AutoJoinHandle(Some(thread)),
sender: sender
}
}
/// Send a request to the service.
pub fn cast(&self, request: Request) {
self.sender.send(request).unwrap();
}
}
//! Some generic code for launching a service.
use std::sync::Mutex;
use std::sync::mpsc::{Sender, channel};
use std::thread::{spawn, JoinHandle};
/// Wrapper around a JoinHandle that automatically joins when dropped.
struct AutoJoinHandle(Option<JoinHandle<()>>);
impl Drop for AutoJoinHandle {
fn drop(&mut self) {
if let Some(thread) = self.0.take() {
thread.join().unwrap();
}
}
}
/// A running Service.
pub struct Service<Request>
{
sender: Mutex<Sender<Request>>,
#[allow(dead_code)] // this is here for its behavior on drop
thread: AutoJoinHandle
}
impl<Request> Service<Request>
where Request: Send + 'static
{
/// Launch a service.
///
/// To stop the service, just drop the value.
///
pub fn new<F>(mut f: F) -> Service<Request>
// Rules about what `f` must be. It must be a closure ... that takes a
// single `Request` argument ... that can be sent to another thread.
where F: FnMut(Request) + Send + 'static
{
let (sender, receiver) = channel();
let thread = spawn(move || {
for request in receiver {
f(request);
}
});
Service {
sender: Mutex::new(sender),
thread: AutoJoinHandle(Some(thread))
}
}
/// Send a request to the service.
pub fn cast(&self, request: Request) {
let sender = self.sender.lock().unwrap();
sender.send(request).unwrap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment