1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//! # UDP
//! The constructor every UDP task is started from
use crate;
/// Sends and receives datagrams over UDP
///
/// It doesn't implement `Task`, so a method has to be called on
/// it to get something that does
///
/// ## Behaviour
/// [`Udp::bind`] hands back a [`UdpSocket`], and its methods build
/// the tasks that send and receive on it
///
/// ```no_run
/// # use atap::{Runtime, udp::Udp};
/// # use std::time::Duration;
/// # fn main() -> Result<(), atap::RuntimeError> {
/// let socket = Runtime::block(Udp::bind("127.0.0.1:0"))?;
///
/// Runtime::block(socket.send_to("127.0.0.1:9000", b"ping".as_slice()))?;
/// let (reply, from) = Runtime::task(socket.recv_from())
/// .timeout(Duration::from_secs(1))
/// .spawn()
/// .join()??;
/// # Ok(())
/// # }
/// ```
///
/// ## Waiting
/// A spawned receive waiting for a datagram holds no thread, the
/// same as a TCP one. A blocking call waits on the calling thread,
/// and can't be cancelled or timed out
///
/// #### Note
/// A socket task still waiting on the network when the runtime
/// shuts down is written off, and reads [`RuntimeError::TaskFailed`]
///
/// [`UdpSocket`]: crate::udp::UdpSocket
/// [`RuntimeError::TaskFailed`]: crate::RuntimeError::TaskFailed
;