1use core::hash::Hash;
2use std::cmp::Ordering;
34use crate::host::descriptor::File;
56/// 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}
1415impl Key {
16pub fn new(fd: i32, file: File) -> Self {
17Self { fd, file }
18 }
1920pub fn file(&self) -> &File {
21&self.file
22 }
23}
2425impl Eq for Key {}
2627impl PartialEq for Key {
28fn eq(&self, other: &Self) -> bool {
29self.fd == other.fd && self.file.canonical_handle() == other.file.canonical_handle()
30 }
31}
3233impl Hash for Key {
34fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
35self.fd.hash(state);
36self.file.canonical_handle().hash(state);
37 }
38}
3940/// 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}
4849impl 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.
55pub fn new(pri: u64, key: Key) -> Self {
56Self { pri, key }
57 }
5859pub fn priority(&self) -> u64 {
60self.pri
61 }
62}
6364impl Eq for PriorityKey {}
6566impl PartialEq for PriorityKey {
67fn eq(&self, other: &Self) -> bool {
68// Equality is based only on the priority value as explained in `PriorityKey::new()`.
69self.pri.eq(&other.pri)
70 }
71}
7273impl Ord for PriorityKey {
74fn cmp(&self, other: &Self) -> Ordering {
75// Order is based only on the priority value as explained in `PriorityKey::new()`.
76self.pri.cmp(&other.pri)
77 }
78}
7980impl PartialOrd for PriorityKey {
81fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
82Some(self.cmp(other))
83 }
84}
8586impl From<PriorityKey> for Key {
87fn from(value: PriorityKey) -> Self {
88 value.key
89 }
90}