aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-04-14 09:23:12 +0000
committerFuwn <[email protected]>2026-04-14 09:23:12 +0000
commit8030bba615ba1aaad6c31fbbe7a5d1bc31dc098e (patch)
treefc847483711476c407811ede02fea83641fcfedc
parentperf(router)!: Pass RouteContext by reference to Partial headers and footers (diff)
downloadarchived-windmark-8030bba615ba1aaad6c31fbbe7a5d1bc31dc098e.tar.xz
archived-windmark-8030bba615ba1aaad6c31fbbe7a5d1bc31dc098e.zip
perf(router)!: Replace per-request locks with lock-free frozen storage
-rw-r--r--src/handler/hooks/post_route.rs6
-rw-r--r--src/handler/hooks/pre_route.rs6
-rw-r--r--src/handler/partial.rs6
-rw-r--r--src/router.rs63
4 files changed, 41 insertions, 40 deletions
diff --git a/src/handler/hooks/post_route.rs b/src/handler/hooks/post_route.rs
index 1e1a6b6..0a6e6b7 100644
--- a/src/handler/hooks/post_route.rs
+++ b/src/handler/hooks/post_route.rs
@@ -2,13 +2,13 @@ use crate::{context::HookContext, response::Response};
#[allow(clippy::module_name_repetitions)]
pub trait PostRouteHook: Send + Sync {
- fn call(&mut self, context: &HookContext, response: &mut Response);
+ fn call(&self, context: &HookContext, response: &mut Response);
}
impl<T> PostRouteHook for T
-where T: FnMut(&HookContext, &mut Response) + Send + Sync
+where T: Fn(&HookContext, &mut Response) + Send + Sync
{
- fn call(&mut self, context: &HookContext, response: &mut Response) {
+ fn call(&self, context: &HookContext, response: &mut Response) {
(*self)(context, response);
}
}
diff --git a/src/handler/hooks/pre_route.rs b/src/handler/hooks/pre_route.rs
index 1d11d66..322969c 100644
--- a/src/handler/hooks/pre_route.rs
+++ b/src/handler/hooks/pre_route.rs
@@ -2,11 +2,11 @@ use crate::context::HookContext;
#[allow(clippy::module_name_repetitions)]
pub trait PreRouteHook: Send + Sync {
- fn call(&mut self, context: &HookContext);
+ fn call(&self, context: &HookContext);
}
impl<T> PreRouteHook for T
-where T: FnMut(&HookContext) + Send + Sync
+where T: Fn(&HookContext) + Send + Sync
{
- fn call(&mut self, context: &HookContext) { (*self)(context) }
+ fn call(&self, context: &HookContext) { (*self)(context) }
}
diff --git a/src/handler/partial.rs b/src/handler/partial.rs
index a52fa59..a552096 100644
--- a/src/handler/partial.rs
+++ b/src/handler/partial.rs
@@ -2,11 +2,11 @@ use crate::context::RouteContext;
#[allow(clippy::module_name_repetitions)]
pub trait Partial: Send + Sync {
- fn call(&mut self, context: &RouteContext) -> String;
+ fn call(&self, context: &RouteContext) -> String;
}
impl<T> Partial for T
-where T: FnMut(&RouteContext) -> String + Send + Sync
+where T: Fn(&RouteContext) -> String + Send + Sync
{
- fn call(&mut self, context: &RouteContext) -> String { (*self)(context) }
+ fn call(&self, context: &RouteContext) -> String { (*self)(context) }
}
diff --git a/src/router.rs b/src/router.rs
index d71c961..e0726fd 100644
--- a/src/router.rs
+++ b/src/router.rs
@@ -86,8 +86,8 @@ pub struct Router {
default_logger: bool,
#[cfg(feature = "logger")]
log_filter: String,
- pre_route_callback: Arc<Mutex<Box<dyn PreRouteHook>>>,
- post_route_callback: Arc<Mutex<Box<dyn PostRouteHook>>>,
+ pre_route_callback: Arc<Box<dyn PreRouteHook>>,
+ post_route_callback: Arc<Box<dyn PostRouteHook>>,
character_set: String,
languages: Vec<String>,
port: i32,
@@ -100,10 +100,10 @@ pub struct Router {
struct RequestHandler {
routes: matchit::Router<Arc<Box<dyn RouteResponse>>>,
error_handler: Arc<Box<dyn ErrorResponse>>,
- headers: Arc<Mutex<Vec<Box<dyn Partial>>>>,
- footers: Arc<Mutex<Vec<Box<dyn Partial>>>>,
- pre_route_callback: Arc<Mutex<Box<dyn PreRouteHook>>>,
- post_route_callback: Arc<Mutex<Box<dyn PostRouteHook>>>,
+ headers: Arc<[Box<dyn Partial>]>,
+ footers: Arc<[Box<dyn Partial>]>,
+ pre_route_callback: Arc<Box<dyn PreRouteHook>>,
+ post_route_callback: Arc<Box<dyn PostRouteHook>>,
character_set: String,
languages: Vec<String>,
async_modules: Arc<AsyncMutex<Vec<Box<dyn AsyncModule + Send>>>>,
@@ -207,9 +207,7 @@ impl RequestHandler {
}
}
- if let Ok(mut callback) = self.pre_route_callback.lock() {
- callback.call(&hook_context);
- }
+ self.pre_route_callback.call(&hook_context);
let mut content = if let Ok(ref route) = route {
let route_context = RouteContext::new(
@@ -219,20 +217,15 @@ impl RequestHandler {
peer_certificate,
);
- {
- let mut headers = self.headers.lock().expect("headers lock poisoned");
-
- for partial_header in &mut *headers {
- writeln!(&mut header, "{}", partial_header.call(&route_context),)
- .expect("failed to write header");
- }
+ for partial_header in self.headers.iter() {
+ writeln!(&mut header, "{}", partial_header.call(&route_context))
+ .expect("failed to write header");
}
{
- let mut footers = self.footers.lock().expect("footers lock poisoned");
- let length = footers.len();
+ let length = self.footers.len();
- for (i, partial_footer) in footers.iter_mut().enumerate() {
+ for (i, partial_footer) in self.footers.iter().enumerate() {
let _ = write!(
&mut footer,
"{}{}",
@@ -268,9 +261,7 @@ impl RequestHandler {
}
}
- if let Ok(mut callback) = self.post_route_callback.lock() {
- callback.call(&hook_context, &mut content);
- }
+ self.post_route_callback.call(&hook_context, &mut content);
let status_code =
if content.status == 21 || content.status == 22 || content.status == 23 {
@@ -574,8 +565,20 @@ impl Router {
let handler = Arc::new(RequestHandler {
routes: self.routes.clone(),
error_handler: self.error_handler.clone(),
- headers: self.headers.clone(),
- footers: self.footers.clone(),
+ headers: self
+ .headers
+ .lock()
+ .expect("headers lock poisoned")
+ .drain(..)
+ .collect::<Vec<_>>()
+ .into(),
+ footers: self
+ .footers
+ .lock()
+ .expect("footers lock poisoned")
+ .drain(..)
+ .collect::<Vec<_>>()
+ .into(),
pre_route_callback: self.pre_route_callback.clone(),
post_route_callback: self.post_route_callback.clone(),
character_set: self.character_set.clone(),
@@ -763,7 +766,7 @@ impl Router {
&mut self,
callback: impl PreRouteHook + 'static,
) -> &mut Self {
- self.pre_route_callback = Arc::new(Mutex::new(Box::new(callback)));
+ self.pre_route_callback = Arc::new(Box::new(callback));
self
}
@@ -789,7 +792,7 @@ impl Router {
&mut self,
callback: impl PostRouteHook + 'static,
) -> &mut Self {
- self.post_route_callback = Arc::new(Mutex::new(Box::new(callback)));
+ self.post_route_callback = Arc::new(Box::new(callback));
self
}
@@ -1126,12 +1129,10 @@ impl Default for Router {
default_logger: false,
#[cfg(feature = "logger")]
log_filter: String::new(),
- pre_route_callback: Arc::new(Mutex::new(Box::new(
- (|_| {}) as fn(&HookContext),
- ))),
- post_route_callback: Arc::new(Mutex::new(Box::new(
+ pre_route_callback: Arc::new(Box::new((|_| {}) as fn(&HookContext))),
+ post_route_callback: Arc::new(Box::new(
(|_, _: &mut Response| {}) as fn(&HookContext, &mut Response),
- ))),
+ )),
character_set: "utf-8".to_string(),
languages: vec!["en".to_string()],
port: 1965,