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}