asyncio/async/
wrap.rs

1use unsafe_cell::UnsafeRefCell;
2use error::ErrCode;
3use core::{IoContext, ThreadIoContext, FnOp, Upcast};
4use async::{Sender, NullReceiver, Operation, WrappedHandler, Handler};
5
6use std::sync::Arc;
7use std::marker::PhantomData;
8
9/// The binding Arc handler.
10pub struct ArcHandler<T, F, R, E> {
11    data: Arc<T>,
12    handler: F,
13    _marker: PhantomData<(R, E)>,
14}
15
16impl<T, F, R, E> ArcHandler<T, F, R, E>
17    where T: Send + Sync + 'static,
18          F: FnOnce(Arc<T>, Result<R, E>) + Send + 'static,
19          R: Send + 'static,
20          E: Send + 'static,
21{
22    fn send(self, _: &IoContext, res: Result<R, E>) {
23        let ArcHandler { data, handler, _marker } = self;
24        handler(data, res)
25    }
26}
27
28impl<T, F, R, E> Handler<R, E> for ArcHandler<T, F, R, E>
29    where T: Send + Sync + 'static,
30          F: FnOnce(Arc<T>, Result<R, E>) + Send + 'static,
31          R: Send + 'static,
32          E: Send + 'static,
33{
34    type Output = ();
35
36    type Receiver = NullReceiver;
37
38    fn channel<G>(self, op: G) -> (Operation<R, E, G>, Self::Receiver)
39        where G: WrappedHandler<R, E> + Send + 'static,
40    {
41        (Box::new((self, op)), NullReceiver)
42    }
43
44    fn result(self, _: &IoContext, res: Result<R, E>) -> Self::Output {
45        let ArcHandler { data, handler, _marker } = self;
46        handler(data, res)
47    }
48}
49
50impl<T, F, R, E, G> Upcast<FnOp + Send> for (ArcHandler<T, F, R, E>, G)
51    where T: Send + Sync + 'static,
52          F: FnOnce(Arc<T>, Result<R, E>) + Send + 'static,
53          R: Send + 'static,
54          E: Send + 'static,
55          G: WrappedHandler<R, E> + Send + 'static,
56{
57    fn upcast(self: Box<Self>) -> Box<FnOp + Send> {
58        self
59    }
60}
61
62impl<T, F, R, E, G> Sender<R, E, G> for (ArcHandler<T, F, R, E>, G)
63    where T: Send + Sync + 'static,
64          F: FnOnce(Arc<T>, Result<R, E>) + Send + 'static,
65          R: Send + 'static,
66          E: Send + 'static,
67          G: WrappedHandler<R, E> + Send + 'static,
68{
69    fn send(self: Box<Self>, ctx: &IoContext, res: Result<R, E>) {
70        ctx.post(move|ctx| self.0.send(ctx, res))
71    }
72
73    fn as_self(&self) -> &G {
74        &self.1
75    }
76
77    fn as_mut_self(&mut self) -> &mut G {
78        &mut self.1
79    }
80}
81
82impl<T, F, R, E, G> FnOp for (ArcHandler<T, F, R, E>, G)
83    where T: Send + Sync + 'static,
84          F: FnOnce(Arc<T>, Result<R, E>) + Send + 'static,
85          R: Send + 'static,
86          E: Send + 'static,
87          G: WrappedHandler<R, E> + Send + 'static,
88{
89    fn call_op(self: Box<Self>, ctx: &IoContext, this: &mut ThreadIoContext, ec: ErrCode) {
90        let mut g = UnsafeRefCell::new(&self.1);
91        unsafe { g.as_mut() }.perform(ctx, this, ec, self)
92    }
93}
94
95/// Provides a `Arc` handler to asynchronous operation.
96///
97/// The ArcHandler has trait the `Handler`, that type of `Handler::Output` is `()`.
98///
99/// # Examples
100///
101/// ```
102/// use std::io;
103/// use std::sync::{Arc, Mutex};
104/// use asyncio::{IoContext, wrap};
105/// use asyncio::ip::{IpProtocol, Tcp, TcpSocket, TcpEndpoint, TcpListener};
106///
107/// fn on_accept(soc: Arc<Mutex<TcpListener>>, res: io::Result<(TcpSocket, TcpEndpoint)>) {
108///   if let Ok((acc, ep)) = res {
109///     println!("accepted {}", ep)
110///   }
111/// }
112///
113/// let ctx = &IoContext::new().unwrap();
114/// let soc = Arc::new(Mutex::new(TcpListener::new(ctx, Tcp::v4()).unwrap()));
115/// soc.lock().unwrap().async_accept(wrap(on_accept, &soc));
116/// ```
117pub fn wrap<T, F, R, E>(handler: F, data: &Arc<T>) -> ArcHandler<T, F, R, E> {
118    ArcHandler {
119        data: data.clone(),
120        handler: handler,
121        _marker: PhantomData,
122    }
123}