Skip to content

Commit

Permalink
Re-introduce a token invalidation mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
elinorbgr committed Oct 5, 2023
1 parent 3cb03fb commit 71b6e63
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 189 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

#### Additions

- `Token` and `RegistrationToken` are now invalidated when the event source they represent is removed from the event loop.

#### Bugfixes

- Fix an issue, where id-reuse could execute a PostAction on a newly registered event source
Expand Down
28 changes: 14 additions & 14 deletions src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ use futures_io::{AsyncRead, AsyncWrite, IoSlice, IoSliceMut};

use crate::loop_logic::EventIterator;
use crate::{
loop_logic::{LoopInner, MAX_SOURCES_MASK},
sources::EventDispatcher,
Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory,
loop_logic::LoopInner, sources::EventDispatcher, Interest, Mode, Poll, PostAction, Readiness,
Token, TokenFactory,
};
use crate::{AdditionalLifecycleEventsSet, RegistrationToken};

Expand Down Expand Up @@ -62,8 +61,13 @@ impl<'l, F: AsFd> Async<'l, F> {
interest: Interest::EMPTY,
last_readiness: Readiness::EMPTY,
}));
let key = inner.sources.borrow_mut().insert(Some(dispatcher.clone()));
dispatcher.borrow_mut().token = Some(Token { key });

{
let mut sources = inner.sources.borrow_mut();
let slot = sources.vacant_entry();
slot.source = Some(dispatcher.clone());
dispatcher.borrow_mut().token = Some(Token { inner: slot.token });
}

// SAFETY: We are sure to deregister on drop.
unsafe {
Expand Down Expand Up @@ -198,17 +202,13 @@ impl<'l, Data> IoLoopInner for LoopInner<'l, Data> {
}

fn kill(&self, dispatcher: &RefCell<IoDispatcher>) {
let key = dispatcher
let token = dispatcher
.borrow()
.token
.expect("No token for IO dispatcher")
.key
& MAX_SOURCES_MASK;
let _source = self
.sources
.borrow_mut()
.try_remove(key)
.expect("Attempting to remove a non-existent source?!");
.expect("No token for IO dispatcher");
if let Ok(slot) = self.sources.borrow_mut().get_mut(token.inner) {
slot.source = None;
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ pub mod error;
pub use error::{Error, InsertError, Result};

pub mod io;
mod list;
mod loop_logic;
mod macros;
mod sources;
mod token;
71 changes: 71 additions & 0 deletions src/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::rc::Rc;

use crate::sources::EventDispatcher;
use crate::token::TokenInner;

pub(crate) struct SourceEntry<'l, Data> {
pub(crate) token: TokenInner,
pub(crate) source: Option<Rc<dyn EventDispatcher<Data> + 'l>>,
}

pub(crate) struct SourceList<'l, Data> {
sources: Vec<SourceEntry<'l, Data>>,
}

impl<'l, Data> SourceList<'l, Data> {
pub(crate) fn new() -> Self {
SourceList {
sources: Vec::new(),
}
}

pub(crate) fn vacant_entry(&mut self) -> &mut SourceEntry<'l, Data> {
let opt_id = self.sources.iter().position(|slot| slot.source.is_none());
match opt_id {
Some(id) => {
// we are reusing a slot
let slot = &mut self.sources[id];
// increment the slot version
slot.token = slot.token.increment_version();
slot
}
None => {
// we are inserting a new slot
let next_id = self.sources.len();
self.sources.push(SourceEntry {
token: TokenInner::new(self.sources.len())
.expect("Trying to insert too many sources in an event loop."),
source: None,
});
&mut self.sources[next_id]
}
}
}

pub(crate) fn get(&self, token: TokenInner) -> crate::Result<&SourceEntry<'l, Data>> {
let entry = self
.sources
.get(token.get_id())
.ok_or(crate::Error::InvalidToken)?;
if entry.token.same_source_as(token) {
Ok(entry)
} else {
Err(crate::Error::InvalidToken)
}
}

pub(crate) fn get_mut(
&mut self,
token: TokenInner,
) -> crate::Result<&mut SourceEntry<'l, Data>> {
let entry = self
.sources
.get_mut(token.get_id())
.ok_or(crate::Error::InvalidToken)?;
if entry.token.same_source_as(token) {
Ok(entry)
} else {
Err(crate::Error::InvalidToken)
}
}
}
Loading

0 comments on commit 71b6e63

Please sign in to comment.