summaryrefslogtreecommitdiffstats
path: root/third_party/rust/mio/src/sys/windows/event.rs
blob: a49252a2969b727e7a9b6840dec927aec2539f88 (plain)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use std::fmt;

use miow::iocp::CompletionStatus;

use super::afd;
use crate::Token;

#[derive(Clone)]
pub struct Event {
    pub flags: u32,
    pub data: u64,
}

pub fn token(event: &Event) -> Token {
    Token(event.data as usize)
}

impl Event {
    pub(super) fn new(token: Token) -> Event {
        Event {
            flags: 0,
            data: usize::from(token) as u64,
        }
    }

    pub(super) fn set_readable(&mut self) {
        self.flags |= afd::POLL_RECEIVE
    }

    #[cfg(feature = "os-ext")]
    pub(super) fn set_writable(&mut self) {
        self.flags |= afd::POLL_SEND;
    }

    pub(super) fn from_completion_status(status: &CompletionStatus) -> Event {
        Event {
            flags: status.bytes_transferred(),
            data: status.token() as u64,
        }
    }

    pub(super) fn to_completion_status(&self) -> CompletionStatus {
        CompletionStatus::new(self.flags, self.data as usize, std::ptr::null_mut())
    }
}

pub(crate) const READABLE_FLAGS: u32 = afd::POLL_RECEIVE
    | afd::POLL_DISCONNECT
    | afd::POLL_ACCEPT
    | afd::POLL_ABORT
    | afd::POLL_CONNECT_FAIL;
pub(crate) const WRITABLE_FLAGS: u32 = afd::POLL_SEND | afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;
pub(crate) const ERROR_FLAGS: u32 = afd::POLL_CONNECT_FAIL;
pub(crate) const READ_CLOSED_FLAGS: u32 =
    afd::POLL_DISCONNECT | afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;
pub(crate) const WRITE_CLOSED_FLAGS: u32 = afd::POLL_ABORT | afd::POLL_CONNECT_FAIL;

pub fn is_readable(event: &Event) -> bool {
    event.flags & READABLE_FLAGS != 0
}

pub fn is_writable(event: &Event) -> bool {
    event.flags & WRITABLE_FLAGS != 0
}

pub fn is_error(event: &Event) -> bool {
    event.flags & ERROR_FLAGS != 0
}

pub fn is_read_closed(event: &Event) -> bool {
    event.flags & READ_CLOSED_FLAGS != 0
}

pub fn is_write_closed(event: &Event) -> bool {
    event.flags & WRITE_CLOSED_FLAGS != 0
}

pub fn is_priority(event: &Event) -> bool {
    event.flags & afd::POLL_RECEIVE_EXPEDITED != 0
}

pub fn is_aio(_: &Event) -> bool {
    // Not supported.
    false
}

pub fn is_lio(_: &Event) -> bool {
    // Not supported.
    false
}

pub fn debug_details(f: &mut fmt::Formatter<'_>, event: &Event) -> fmt::Result {
    #[allow(clippy::trivially_copy_pass_by_ref)]
    fn check_flags(got: &u32, want: &u32) -> bool {
        (got & want) != 0
    }
    debug_detail!(
        FlagsDetails(u32),
        check_flags,
        afd::POLL_RECEIVE,
        afd::POLL_RECEIVE_EXPEDITED,
        afd::POLL_SEND,
        afd::POLL_DISCONNECT,
        afd::POLL_ABORT,
        afd::POLL_LOCAL_CLOSE,
        afd::POLL_CONNECT,
        afd::POLL_ACCEPT,
        afd::POLL_CONNECT_FAIL,
    );

    f.debug_struct("event")
        .field("flags", &FlagsDetails(event.flags))
        .field("data", &event.data)
        .finish()
}

pub struct Events {
    /// Raw I/O event completions are filled in here by the call to `get_many`
    /// on the completion port above. These are then processed to run callbacks
    /// which figure out what to do after the event is done.
    pub statuses: Box<[CompletionStatus]>,

    /// Literal events returned by `get` to the upwards `EventLoop`. This file
    /// doesn't really modify this (except for the waker), instead almost all
    /// events are filled in by the `ReadinessQueue` from the `poll` module.
    pub events: Vec<Event>,
}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        // Note that it's possible for the output `events` to grow beyond the
        // capacity as it can also include deferred events, but that's certainly
        // not the end of the world!
        Events {
            statuses: vec![CompletionStatus::zero(); cap].into_boxed_slice(),
            events: Vec::with_capacity(cap),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    pub fn len(&self) -> usize {
        self.events.len()
    }

    pub fn get(&self, idx: usize) -> Option<&Event> {
        self.events.get(idx)
    }

    pub fn clear(&mut self) {
        self.events.clear();
        for status in self.statuses.iter_mut() {
            *status = CompletionStatus::zero();
        }
    }
}