mtcp_rs/canceller.rs
1/*
2 * mtcp - TcpListener/TcpStream *with* timeout/cancellation support
3 * This is free and unencumbered software released into the public domain.
4 */
5use std::io::Result;
6use std::sync::Arc;
7
8use crate::utilities::Flag;
9
10/// A canceller that can be used to abort "pending" I/O operations
11///
12/// Each `mtcp_rs::TcpCanceller` instance is tied to an
13/// [`mtcp_rs::TcpManager`](crate::TcpManager) instance. Calling the
14/// [`cancel()`](TcpCanceller::cancel()) function will *immediately* abort
15/// ***any*** pending I/O operations in ***all***
16/// [`mtcp_rs::TcpListener`](crate::TcpListener) or
17/// [`mtcp_rs::TcpStream`](crate::TcpStream) instances that are tied to the same
18/// `mtcp_rs::TcpManager` instance. Unlike the `mtcp_rs::TcpManager` instance, the
19/// `mtcp_rs::TcpCanceller` instance *can* be moved across the thread boundary.
20/// This is useful, for example, to implement a Ctrl+C (SIGINT) handler.
21///
22/// Cancelled I/O operations will fail with an
23/// [`TcpError::Cancelled`](crate::TcpError::Cancelled) error. However, there
24/// is **no** guarantee that I/O operations already in progress will actually
25/// be cancelled! Even after cancellation has been requested, an I/O operation
26/// that was just about to finish may still succeed, or even fail with a
27/// different error. Newly started operations *are* guaranteed to be cancelled.
28#[derive(Debug)]
29pub struct TcpCanceller {
30 flag: Arc<Flag>,
31}
32
33impl TcpCanceller {
34 pub(crate) fn from(flag: Arc<Flag>) -> Self {
35 Self {
36 flag,
37 }
38 }
39
40 /// Request cancellation of any pending I/O operations belonging to the
41 /// tied `TcpManager` instance.
42 ///
43 /// Returns `true`, if cancellation was requested successfully; or `false`,
44 /// if the tied `TcpManager` was already cancelled before.
45 pub fn cancel(&self) -> Result<bool> {
46 self.flag.raise()
47 }
48
49 /// Check whether the tied `TcpManager` instance has been
50 /// [cancelled](Self::cancel) yet.
51 ///
52 /// Returns `true`, if cancellation has been requested for the tied
53 /// `TcpManager`; or `false` otherwise.
54 pub fn cancelled(&self) -> bool {
55 self.flag.check()
56 }
57}