mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
Remove the shim kernel crate
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
d76c7a5b1e
commit
dafd16075f
44
kernel/src/events/events.rs
Normal file
44
kernel/src/events/events.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// A trait to represent any events.
|
||||
///
|
||||
/// # The unit event
|
||||
///
|
||||
/// The unit type `()` can serve as a unit event.
|
||||
/// It can be used if there is only one kind of event
|
||||
/// and the event carries no additional information.
|
||||
pub trait Events: Copy + Clone + Send + Sync + 'static {}
|
||||
|
||||
impl Events for () {}
|
||||
|
||||
/// A trait to filter events.
|
||||
///
|
||||
/// # The no-op event filter
|
||||
///
|
||||
/// The unit type `()` can serve as a no-op event filter.
|
||||
/// It implements `EventsFilter<E>` for any events type `E`,
|
||||
/// with a `filter` method that always returns `true`.
|
||||
/// If the `F` type of `Subject<E, F>` is not specified explicitly,
|
||||
/// then the unit type `()` is chosen as the event filter.
|
||||
///
|
||||
/// # Per-object event filter
|
||||
///
|
||||
/// Any `Option<F: EventsFilter>` is also an event filter thanks to
|
||||
/// the blanket implementations the `EventsFilter` trait.
|
||||
/// By using `Option<F: EventsFilter>`, we can decide, on a per-observer basis,
|
||||
/// if an observer needs an event filter.
|
||||
pub trait EventsFilter<E: Events>: Send + Sync + 'static {
|
||||
fn filter(&self, event: &E) -> bool;
|
||||
}
|
||||
|
||||
impl<E: Events> EventsFilter<E> for () {
|
||||
fn filter(&self, _events: &E) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Events, F: EventsFilter<E>> EventsFilter<E> for Option<F> {
|
||||
fn filter(&self, events: &E) -> bool {
|
||||
self.as_ref().map_or(true, |f| f.filter(events))
|
||||
}
|
||||
}
|
25
kernel/src/events/io_events.rs
Normal file
25
kernel/src/events/io_events.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{Events, EventsFilter};
|
||||
|
||||
crate::bitflags! {
|
||||
pub struct IoEvents: u32 {
|
||||
const IN = 0x0001;
|
||||
const PRI = 0x0002;
|
||||
const OUT = 0x0004;
|
||||
const ERR = 0x0008;
|
||||
const HUP = 0x0010;
|
||||
const NVAL = 0x0020;
|
||||
const RDHUP = 0x2000;
|
||||
/// Events that are always polled even without specifying them.
|
||||
const ALWAYS_POLL = Self::ERR.bits | Self::HUP.bits;
|
||||
}
|
||||
}
|
||||
|
||||
impl Events for IoEvents {}
|
||||
|
||||
impl EventsFilter<IoEvents> for IoEvents {
|
||||
fn filter(&self, events: &IoEvents) -> bool {
|
||||
self.intersects(*events)
|
||||
}
|
||||
}
|
15
kernel/src/events/mod.rs
Normal file
15
kernel/src/events/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#[allow(clippy::module_inception)]
|
||||
mod events;
|
||||
mod io_events;
|
||||
mod observer;
|
||||
mod subject;
|
||||
|
||||
pub use io_events::IoEvents;
|
||||
|
||||
pub use self::{
|
||||
events::{Events, EventsFilter},
|
||||
observer::Observer,
|
||||
subject::Subject,
|
||||
};
|
39
kernel/src/events/observer.rs
Normal file
39
kernel/src/events/observer.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use super::Events;
|
||||
|
||||
/// An observer for events.
|
||||
///
|
||||
/// In a sense, event observers are just a fancy form of callback functions.
|
||||
/// An observer's `on_events` methods are supposed to be called when
|
||||
/// some events that are interesting to the observer happen.
|
||||
///
|
||||
/// # The no-op observer
|
||||
///
|
||||
/// The unit type `()` can serve as a no-op observer.
|
||||
/// It implements `Observer<E>` for any events type `E`,
|
||||
/// with an `on_events` method that simply does nothing.
|
||||
///
|
||||
/// It can be used to create an empty `Weak`, as shown in the example below.
|
||||
/// Using the unit type is necessary, as creating an empty `Weak` needs to
|
||||
/// have a sized type (e.g. the unit type).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use alloc::sync::Weak;
|
||||
/// use crate::events::Observer;
|
||||
///
|
||||
/// let empty: Weak<dyn Observer<()>> = Weak::<()>::new();
|
||||
/// assert!(empty.upgrade().is_empty());
|
||||
/// ```
|
||||
pub trait Observer<E: Events>: Send + Sync {
|
||||
/// Notify the observer that some interesting events happen.
|
||||
fn on_events(&self, events: &E);
|
||||
}
|
||||
|
||||
impl<E: Events> Observer<E> for () {
|
||||
fn on_events(&self, events: &E) {}
|
||||
}
|
93
kernel/src/events/subject.rs
Normal file
93
kernel/src/events/subject.rs
Normal file
@ -0,0 +1,93 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use keyable_arc::KeyableWeak;
|
||||
|
||||
use super::{Events, EventsFilter, Observer};
|
||||
use crate::prelude::*;
|
||||
|
||||
/// A Subject notifies interesting events to registered observers.
|
||||
pub struct Subject<E: Events, F: EventsFilter<E> = ()> {
|
||||
// A table that maintains all interesting observers.
|
||||
observers: Mutex<BTreeMap<KeyableWeak<dyn Observer<E>>, F>>,
|
||||
// To reduce lock contentions, we maintain a counter for the size of the table
|
||||
num_observers: AtomicUsize,
|
||||
}
|
||||
|
||||
impl<E: Events, F: EventsFilter<E>> Subject<E, F> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
observers: Mutex::new(BTreeMap::new()),
|
||||
num_observers: AtomicUsize::new(0),
|
||||
}
|
||||
}
|
||||
/// Register an observer.
|
||||
///
|
||||
/// A registered observer will get notified through its `on_events` method.
|
||||
/// If events `filter` is provided, only filtered events will notify the observer.
|
||||
///
|
||||
/// If the given observer has already been registered, then its registered events
|
||||
/// filter will be updated.
|
||||
pub fn register_observer(&self, observer: Weak<dyn Observer<E>>, filter: F) {
|
||||
let mut observers = self.observers.lock();
|
||||
let is_new = {
|
||||
let observer: KeyableWeak<dyn Observer<E>> = observer.into();
|
||||
observers.insert(observer, filter).is_none()
|
||||
};
|
||||
if is_new {
|
||||
self.num_observers.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unregister an observer.
|
||||
///
|
||||
/// If such an observer is found, then the registered observer will be
|
||||
/// removed from the subject and returned as the return value. Otherwise,
|
||||
/// a `None` will be returned.
|
||||
pub fn unregister_observer(
|
||||
&self,
|
||||
observer: &Weak<dyn Observer<E>>,
|
||||
) -> Option<Weak<dyn Observer<E>>> {
|
||||
let observer: KeyableWeak<dyn Observer<E>> = observer.clone().into();
|
||||
let mut observers = self.observers.lock();
|
||||
let observer = observers
|
||||
.remove_entry(&observer)
|
||||
.map(|(observer, _)| observer.into());
|
||||
if observer.is_some() {
|
||||
self.num_observers.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
observer
|
||||
}
|
||||
|
||||
/// Notify events to all registered observers.
|
||||
///
|
||||
/// It will remove the observers which have been freed.
|
||||
pub fn notify_observers(&self, events: &E) {
|
||||
// Fast path.
|
||||
if self.num_observers.load(Ordering::Relaxed) == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slow path: broadcast the new events to all observers.
|
||||
let mut observers = self.observers.lock();
|
||||
observers.retain(|observer, filter| {
|
||||
if let Some(observer) = observer.upgrade() {
|
||||
if !filter.filter(events) {
|
||||
return true;
|
||||
}
|
||||
observer.on_events(events);
|
||||
true
|
||||
} else {
|
||||
self.num_observers.fetch_sub(1, Ordering::Relaxed);
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Events> Default for Subject<E> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user