mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
chore: switch handlers to ArcSwap
faster and yet again i need this for PatchBukkit
This commit is contained in:
@@ -8,11 +8,11 @@ use crate::{
|
||||
LoggerOption, command::client_suggestions, net::ClientPlatform, plugin::PluginMetadata,
|
||||
plugin_log,
|
||||
};
|
||||
use arc_swap::ArcSwap;
|
||||
use pumpkin_util::{
|
||||
PermissionLvl,
|
||||
permission::{Permission, PermissionManager},
|
||||
};
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::Level;
|
||||
|
||||
use crate::{
|
||||
@@ -31,11 +31,11 @@ use super::{EventPriority, Payload};
|
||||
/// # Fields
|
||||
/// - `metadata`: Metadata of the plugin.
|
||||
/// - `server`: A reference to the server on which the plugin operates.
|
||||
/// - `handlers`: A map of event handlers, protected by a read-write lock for safe access across threads.
|
||||
/// - `handlers`: A map of event handlers, wrapped in `ArcSwap` for lock-free read access across threads.
|
||||
pub struct Context {
|
||||
metadata: PluginMetadata,
|
||||
pub server: Arc<Server>,
|
||||
pub handlers: Arc<RwLock<HandlerMap>>,
|
||||
pub handlers: Arc<ArcSwap<HandlerMap>>,
|
||||
pub plugin_manager: Arc<PluginManager>,
|
||||
pub permission_manager: Arc<PermissionManager>,
|
||||
pub logger: Arc<OnceLock<LoggerOption>>,
|
||||
@@ -54,7 +54,7 @@ impl Context {
|
||||
pub fn new(
|
||||
metadata: PluginMetadata,
|
||||
server: Arc<Server>,
|
||||
handlers: Arc<RwLock<HandlerMap>>,
|
||||
handlers: Arc<ArcSwap<HandlerMap>>,
|
||||
plugin_manager: Arc<PluginManager>,
|
||||
logger: Arc<OnceLock<LoggerOption>>,
|
||||
) -> Self {
|
||||
@@ -257,7 +257,7 @@ impl Context {
|
||||
.has_permission(player_uuid, permission, player_op_level)
|
||||
}
|
||||
|
||||
/// Asynchronously registers an event handler for a specific event type.
|
||||
/// Registers an event handler for a specific event type.
|
||||
///
|
||||
/// # Type Parameters
|
||||
/// - `E`: The event type that the handler will respond to.
|
||||
@@ -270,7 +270,7 @@ impl Context {
|
||||
///
|
||||
/// # Constraints
|
||||
/// The handler must implement the `EventHandler<E>` trait.
|
||||
pub async fn register_event<E: Payload + 'static, H>(
|
||||
pub fn register_event<E: Payload + 'static, H>(
|
||||
&self,
|
||||
handler: Arc<H>,
|
||||
priority: EventPriority,
|
||||
@@ -278,19 +278,21 @@ impl Context {
|
||||
) where
|
||||
H: EventHandler<E> + 'static,
|
||||
{
|
||||
let mut handlers = self.handlers.write().await;
|
||||
|
||||
let handlers_vec = handlers
|
||||
.entry(E::get_name_static())
|
||||
.or_insert_with(Vec::new);
|
||||
|
||||
let typed_handler = TypedEventHandler {
|
||||
let typed_handler = Arc::new(TypedEventHandler {
|
||||
handler,
|
||||
priority,
|
||||
blocking,
|
||||
_phantom: std::marker::PhantomData,
|
||||
};
|
||||
handlers_vec.push(Box::new(typed_handler));
|
||||
});
|
||||
|
||||
self.handlers.rcu(|handlers| {
|
||||
let mut new_handlers = (**handlers).clone();
|
||||
new_handlers
|
||||
.entry(E::get_name_static())
|
||||
.or_default()
|
||||
.push(typed_handler.clone());
|
||||
Arc::new(new_handlers)
|
||||
});
|
||||
}
|
||||
|
||||
/// Registers a custom plugin loader that can load additional plugin types.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
use arc_swap::ArcSwap;
|
||||
use futures::future::join_all;
|
||||
use loader::{LoaderError, PluginLoader, native::NativePluginLoader};
|
||||
use notify::{EventKind, RecursiveMode, Watcher, event::ModifyKind};
|
||||
@@ -101,15 +102,15 @@ pub trait EventHandler<E: Payload>: Send + Sync {
|
||||
/// A struct representing a typed event handler.
|
||||
///
|
||||
/// This struct holds a reference to an event handler, its priority, and whether it is blocking.
|
||||
struct TypedEventHandler<E, H>
|
||||
pub struct TypedEventHandler<E, H>
|
||||
where
|
||||
E: Payload + Send + Sync + 'static,
|
||||
H: EventHandler<E> + Send + Sync,
|
||||
{
|
||||
handler: Arc<H>,
|
||||
priority: EventPriority,
|
||||
blocking: bool,
|
||||
_phantom: std::marker::PhantomData<E>,
|
||||
pub handler: Arc<H>,
|
||||
pub priority: EventPriority,
|
||||
pub blocking: bool,
|
||||
pub _phantom: std::marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E, H> DynEventHandler for TypedEventHandler<E, H>
|
||||
@@ -158,7 +159,7 @@ where
|
||||
|
||||
/// A type alias for a map of event handlers, where the key is a static string
|
||||
/// and the value is a vector of dynamic event handlers.
|
||||
type HandlerMap = HashMap<&'static str, Vec<Box<dyn DynEventHandler>>>;
|
||||
pub type HandlerMap = HashMap<&'static str, Vec<Arc<dyn DynEventHandler>>>;
|
||||
|
||||
/// Plugin loading state
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -172,7 +173,7 @@ pub enum PluginState {
|
||||
pub struct PluginManager {
|
||||
plugins: RwLock<Vec<LoadedPlugin>>,
|
||||
loaders: RwLock<Vec<Arc<dyn PluginLoader>>>,
|
||||
handlers: Arc<RwLock<HandlerMap>>,
|
||||
handlers: Arc<ArcSwap<HandlerMap>>,
|
||||
unloaded_files: RwLock<HashSet<PathBuf>>,
|
||||
services: Arc<RwLock<HashMap<String, Arc<dyn Payload>>>>,
|
||||
// Plugin state tracking
|
||||
@@ -227,7 +228,7 @@ impl PluginManager {
|
||||
Arc::new(NativePluginLoader),
|
||||
Arc::new(WasmPluginLoader),
|
||||
]),
|
||||
handlers: Arc::new(RwLock::new(HashMap::new())),
|
||||
handlers: Arc::new(ArcSwap::from_pointee(HashMap::new())),
|
||||
unloaded_files: RwLock::new(HashSet::new()),
|
||||
services: Arc::new(RwLock::new(HashMap::new())),
|
||||
plugin_states: RwLock::new(HashMap::new()),
|
||||
@@ -1090,23 +1091,26 @@ impl PluginManager {
|
||||
}
|
||||
|
||||
/// Register an event handler
|
||||
pub async fn register<E, H>(&self, handler: Arc<H>, priority: EventPriority, blocking: bool)
|
||||
pub fn register<E, H>(&self, handler: Arc<H>, priority: EventPriority, blocking: bool)
|
||||
where
|
||||
E: Payload + Send + Sync + 'static,
|
||||
H: EventHandler<E> + 'static,
|
||||
{
|
||||
let mut handlers = self.handlers.write().await;
|
||||
let typed_handler = TypedEventHandler {
|
||||
let typed_handler = Arc::new(TypedEventHandler {
|
||||
handler,
|
||||
priority,
|
||||
blocking,
|
||||
_phantom: std::marker::PhantomData,
|
||||
};
|
||||
});
|
||||
|
||||
handlers
|
||||
.entry(E::get_name_static())
|
||||
.or_default()
|
||||
.push(Box::new(typed_handler));
|
||||
self.handlers.rcu(|handlers| {
|
||||
let mut new_handlers = (**handlers).clone();
|
||||
new_handlers
|
||||
.entry(E::get_name_static())
|
||||
.or_default()
|
||||
.push(typed_handler.clone());
|
||||
Arc::new(new_handlers)
|
||||
});
|
||||
}
|
||||
|
||||
/// Fire an event to all registered handlers
|
||||
@@ -1115,12 +1119,12 @@ impl PluginManager {
|
||||
server: &Arc<Server>,
|
||||
event: &mut E,
|
||||
) {
|
||||
let handlers_lock = self.handlers.read().await;
|
||||
if handlers_lock.is_empty() {
|
||||
let handlers_map = self.handlers.load();
|
||||
if handlers_map.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(handlers) = handlers_lock.get(&E::get_name_static()) else {
|
||||
let Some(handlers) = handlers_map.get(E::get_name_static()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user