shadow_rs/host/descriptor/epoll/
key.rs

1use core::hash::Hash;
2use std::cmp::Ordering;
3
4use crate::host::descriptor::File;
5
6/// A `Key` helps us find an epoll entry given the fd and `File` object available at the time that a
7/// syscall is made. Epoll uses `Key`s to be able to add the same `File` multiple times under
8/// different fds, and add the same fd multiple times as long as the `File` is different.
9#[derive(Clone)]
10pub(super) struct Key {
11    fd: i32,
12    file: File,
13}
14
15impl Key {
16    pub fn new(fd: i32, file: File) -> Self {
17        Self { fd, file }
18    }
19
20    pub fn file(&self) -> &File {
21        &self.file
22    }
23}
24
25impl Eq for Key {}
26
27impl PartialEq for Key {
28    fn eq(&self, other: &Self) -> bool {
29        self.fd == other.fd && self.file.canonical_handle() == other.file.canonical_handle()
30    }
31}
32
33impl Hash for Key {
34    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
35        self.fd.hash(state);
36        self.file.canonical_handle().hash(state);
37    }
38}
39
40/// A `PriorityKey` helps us sort keys by a given priority. We use monitonically increasing priority
41/// values to ensure fairness when reporting events (so that we don't always report events from the
42/// same entry first and starve other entries). Using unique priority values for every key also
43/// ensure deterministic sorting.
44pub(super) struct PriorityKey {
45    pri: u64,
46    key: Key,
47}
48
49impl PriorityKey {
50    /// Creates a new `PriorityKey` with the given priority.
51    ///
52    /// The new key will be tested for equality and order based exclusively on the `pri` value while
53    /// ignoring the `key` value. Thus, callers should ensure that every instance of this object
54    /// that should be considered unique is created with a unique priority value.
55    pub fn new(pri: u64, key: Key) -> Self {
56        Self { pri, key }
57    }
58
59    pub fn priority(&self) -> u64 {
60        self.pri
61    }
62}
63
64impl Eq for PriorityKey {}
65
66impl PartialEq for PriorityKey {
67    fn eq(&self, other: &Self) -> bool {
68        // Equality is based only on the priority value as explained in `PriorityKey::new()`.
69        self.pri.eq(&other.pri)
70    }
71}
72
73impl Ord for PriorityKey {
74    fn cmp(&self, other: &Self) -> Ordering {
75        // Order is based only on the priority value as explained in `PriorityKey::new()`.
76        self.pri.cmp(&other.pri)
77    }
78}
79
80impl PartialOrd for PriorityKey {
81    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
82        Some(self.cmp(other))
83    }
84}
85
86impl From<PriorityKey> for Key {
87    fn from(value: PriorityKey) -> Self {
88        value.key
89    }
90}