Remove unnecessary is_deleted

This commit is contained in:
Ruihan Li 2024-09-01 18:38:11 +08:00 committed by Tate, Hongliang Tian
parent bec2c97637
commit fa52eeb88f

View File

@ -31,7 +31,7 @@ pub struct EpollFile {
// All interesting entries. // All interesting entries.
interest: Mutex<BTreeMap<FileDesc, Arc<EpollEntry>>>, interest: Mutex<BTreeMap<FileDesc, Arc<EpollEntry>>>,
// Entries that are probably ready (having events happened). // Entries that are probably ready (having events happened).
ready: Mutex<VecDeque<Arc<EpollEntry>>>, ready: Mutex<VecDeque<Weak<EpollEntry>>>,
// EpollFile itself is also pollable // EpollFile itself is also pollable
pollee: Pollee, pollee: Pollee,
// Any EpollFile is wrapped with Arc when created. // Any EpollFile is wrapped with Arc when created.
@ -104,10 +104,10 @@ impl EpollFile {
// But unfortunately, deleting an entry from the ready list has a // But unfortunately, deleting an entry from the ready list has a
// complexity of O(N). // complexity of O(N).
// //
// To optimize the performance, we only mark the epoll entry as // To optimize performance, we postpone the actual deletion to the time
// deleted at this moment. The real deletion happens when the ready list // when the ready list is scanned in `EpolFile::wait`. This can be done
// is scanned in EpolFile::wait. // because the strong reference count will reach zero and `Weak::upgrade`
entry.set_deleted(); // will fail.
let file = match entry.file() { let file = match entry.file() {
Some(file) => file, Some(file) => file,
@ -132,9 +132,6 @@ impl EpollFile {
let entry = interest let entry = interest
.get(&fd) .get(&fd)
.ok_or_else(|| Error::with_message(Errno::ENOENT, "fd is not in the interest list"))?; .ok_or_else(|| Error::with_message(Errno::ENOENT, "fd is not in the interest list"))?;
if entry.is_deleted() {
return_errno_with_message!(Errno::ENOENT, "fd is not in the interest list");
}
let new_mask = new_ep_event.events; let new_mask = new_ep_event.events;
entry.update(new_ep_event, new_ep_flags); entry.update(new_ep_event, new_ep_flags);
let entry = entry.clone(); let entry = entry.clone();
@ -203,13 +200,10 @@ impl EpollFile {
fn push_ready(&self, entry: Arc<EpollEntry>) { fn push_ready(&self, entry: Arc<EpollEntry>) {
let mut ready = self.ready.lock(); let mut ready = self.ready.lock();
if entry.is_deleted() {
return;
}
if !entry.is_ready() { if !entry.is_ready() {
entry.set_ready(); entry.set_ready();
ready.push_back(entry); ready.push_back(Arc::downgrade(&entry));
} }
// Even if the entry is already set to ready, there might be new events that we are interested in. // Even if the entry is already set to ready, there might be new events that we are interested in.
@ -233,7 +227,7 @@ impl EpollFile {
} }
let ready_entries: Vec<Arc<EpollEntry>> = ready let ready_entries: Vec<Arc<EpollEntry>> = ready
.drain(..pop_count) .drain(..pop_count)
.filter(|entry| !entry.is_deleted()) .filter_map(|entry| Weak::upgrade(&entry))
.collect(); .collect();
pop_quota -= pop_count; pop_quota -= pop_count;
@ -262,7 +256,7 @@ impl EpollFile {
// If the epoll entry is neither edge-triggered or one-shot, then we should // If the epoll entry is neither edge-triggered or one-shot, then we should
// keep the entry in the ready list. // keep the entry in the ready list.
if !ep_flags.intersects(EpollFlags::ONE_SHOT | EpollFlags::EDGE_TRIGGER) { if !ep_flags.intersects(EpollFlags::ONE_SHOT | EpollFlags::EDGE_TRIGGER) {
ready.push_back(entry); ready.push_back(Arc::downgrade(&entry));
} }
// Otherwise, the entry is indeed removed the ready list and we should reset // Otherwise, the entry is indeed removed the ready list and we should reset
// its ready flag. // its ready flag.
@ -307,7 +301,6 @@ impl Drop for EpollFile {
let fds: Vec<_> = interest let fds: Vec<_> = interest
.extract_if(|_, _| true) .extract_if(|_, _| true)
.map(|(fd, entry)| { .map(|(fd, entry)| {
entry.set_deleted();
if let Some(file) = entry.file() { if let Some(file) = entry.file() {
let _ = file.unregister_observer(&(entry.self_weak() as _)); let _ = file.unregister_observer(&(entry.self_weak() as _));
} }
@ -366,8 +359,6 @@ pub struct EpollEntry {
inner: Mutex<Inner>, inner: Mutex<Inner>,
// Whether the entry is in the ready list // Whether the entry is in the ready list
is_ready: AtomicBool, is_ready: AtomicBool,
// Whether the entry has been deleted from the interest list
is_deleted: AtomicBool,
// Refers to the epoll file containing this epoll entry // Refers to the epoll file containing this epoll entry
weak_epoll: Weak<EpollFile>, weak_epoll: Weak<EpollFile>,
// An EpollEntry is always contained inside Arc // An EpollEntry is always contained inside Arc
@ -393,7 +384,6 @@ impl EpollEntry {
file, file,
inner: Mutex::new(Inner { event, flags }), inner: Mutex::new(Inner { event, flags }),
is_ready: AtomicBool::new(false), is_ready: AtomicBool::new(false),
is_deleted: AtomicBool::new(false),
weak_epoll, weak_epoll,
weak_self: me.clone(), weak_self: me.clone(),
}) })
@ -471,16 +461,6 @@ impl EpollEntry {
self.is_ready.store(false, Ordering::Relaxed) self.is_ready.store(false, Ordering::Relaxed)
} }
/// Returns whether the epoll entry has been deleted from the interest list.
pub fn is_deleted(&self) -> bool {
self.is_deleted.load(Ordering::Relaxed)
}
/// Mark the epoll entry as having been deleted from the interest list.
pub fn set_deleted(&self) {
self.is_deleted.store(true, Ordering::Relaxed);
}
/// Get the file descriptor associated with the epoll entry. /// Get the file descriptor associated with the epoll entry.
pub fn fd(&self) -> FileDesc { pub fn fd(&self) -> FileDesc {
self.fd self.fd
@ -489,11 +469,6 @@ impl EpollEntry {
impl Observer<IoEvents> for EpollEntry { impl Observer<IoEvents> for EpollEntry {
fn on_events(&self, _events: &IoEvents) { fn on_events(&self, _events: &IoEvents) {
// Fast path
if self.is_deleted() {
return;
}
if let Some(epoll_file) = self.epoll_file() { if let Some(epoll_file) = self.epoll_file() {
epoll_file.push_ready(self.self_arc()); epoll_file.push_ready(self.self_arc());
} }