Skip to content

Commit

Permalink
WIP Make HtmlRewriter Send + Sync.
Browse files Browse the repository at this point in the history
  • Loading branch information
orium committed Aug 9, 2024
1 parent 53469c5 commit 61d33f9
Show file tree
Hide file tree
Showing 25 changed files with 211 additions and 166 deletions.
11 changes: 5 additions & 6 deletions src/base/encoding.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::rewriter::AsciiCompatibleEncoding;
use encoding_rs::Encoding;
use std::cell::Cell;
use std::ops::Deref;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

/// A charset encoding that can be shared and modified.
///
Expand All @@ -11,22 +10,22 @@ use std::rc::Rc;
/// [crate::Settings::adjust_charset_on_meta_tag]).
#[derive(Clone)]
pub struct SharedEncoding {
encoding: Rc<Cell<AsciiCompatibleEncoding>>,
encoding: Arc<Mutex<AsciiCompatibleEncoding>>,
}

impl SharedEncoding {
pub fn new(encoding: AsciiCompatibleEncoding) -> SharedEncoding {
SharedEncoding {
encoding: Rc::new(Cell::new(encoding)),
encoding: Arc::new(Mutex::new(encoding)),
}
}

pub fn get(&self) -> &'static Encoding {
self.encoding.get().into()
(*self.encoding.lock().unwrap().deref()).into()
}

pub fn set(&self, encoding: AsciiCompatibleEncoding) {
self.encoding.set(encoding);
*self.encoding.lock().unwrap() = encoding;
}
}

Expand Down
34 changes: 17 additions & 17 deletions src/memory/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Arena {

impl Arena {
pub fn new(limiter: SharedMemoryLimiter, preallocated_size: usize) -> Self {
limiter.borrow_mut().preallocate(preallocated_size);
limiter.lock().unwrap().preallocate(preallocated_size);

Arena {
limiter,
Expand All @@ -27,7 +27,7 @@ impl Arena {

// NOTE: approximate usage, as `Vec::reserve_exact` doesn't
// give guarantees about exact capacity value :).
self.limiter.borrow_mut().increase_usage(additional)?;
self.limiter.lock().unwrap().increase_usage(additional)?;

// NOTE: with wicely choosen preallocated size this branch should be
// executed quite rarely. We can't afford to use double capacity
Expand Down Expand Up @@ -60,24 +60,24 @@ impl Arena {
mod tests {
use super::super::limiter::MemoryLimiter;
use super::*;
use std::rc::Rc;
use std::sync::Arc;

#[test]
fn append() {
let limiter = MemoryLimiter::new_shared(10);
let mut arena = Arena::new(Rc::clone(&limiter), 2);
let mut arena = Arena::new(Arc::clone(&limiter), 2);

arena.append(&[1, 2]).unwrap();
assert_eq!(arena.bytes(), &[1, 2]);
assert_eq!(limiter.borrow().current_usage(), 2);
assert_eq!(limiter.lock().unwrap().current_usage(), 2);

arena.append(&[3, 4]).unwrap();
assert_eq!(arena.bytes(), &[1, 2, 3, 4]);
assert_eq!(limiter.borrow().current_usage(), 4);
assert_eq!(limiter.lock().unwrap().current_usage(), 4);

arena.append(&[5, 6, 7, 8, 9, 10]).unwrap();
assert_eq!(arena.bytes(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
assert_eq!(limiter.borrow().current_usage(), 10);
assert_eq!(limiter.lock().unwrap().current_usage(), 10);

let err = arena.append(&[11]).unwrap_err();

Expand All @@ -87,23 +87,23 @@ mod tests {
#[test]
fn init_with() {
let limiter = MemoryLimiter::new_shared(5);
let mut arena = Arena::new(Rc::clone(&limiter), 0);
let mut arena = Arena::new(Arc::clone(&limiter), 0);

arena.init_with(&[1]).unwrap();
assert_eq!(arena.bytes(), &[1]);
assert_eq!(limiter.borrow().current_usage(), 1);
assert_eq!(limiter.lock().unwrap().current_usage(), 1);

arena.append(&[1, 2]).unwrap();
assert_eq!(arena.bytes(), &[1, 1, 2]);
assert_eq!(limiter.borrow().current_usage(), 3);
assert_eq!(limiter.lock().unwrap().current_usage(), 3);

arena.init_with(&[1, 2, 3]).unwrap();
assert_eq!(arena.bytes(), &[1, 2, 3]);
assert_eq!(limiter.borrow().current_usage(), 3);
assert_eq!(limiter.lock().unwrap().current_usage(), 3);

arena.init_with(&[]).unwrap();
assert_eq!(arena.bytes(), &[]);
assert_eq!(limiter.borrow().current_usage(), 3);
assert_eq!(limiter.lock().unwrap().current_usage(), 3);

let err = arena.init_with(&[1, 2, 3, 4, 5, 6, 7]).unwrap_err();

Expand All @@ -113,24 +113,24 @@ mod tests {
#[test]
fn shift() {
let limiter = MemoryLimiter::new_shared(10);
let mut arena = Arena::new(Rc::clone(&limiter), 0);
let mut arena = Arena::new(Arc::clone(&limiter), 0);

arena.append(&[0, 1, 2, 3]).unwrap();
arena.shift(2);
assert_eq!(arena.bytes(), &[2, 3]);
assert_eq!(limiter.borrow().current_usage(), 4);
assert_eq!(limiter.lock().unwrap().current_usage(), 4);

arena.append(&[0, 1]).unwrap();
assert_eq!(arena.bytes(), &[2, 3, 0, 1]);
assert_eq!(limiter.borrow().current_usage(), 4);
assert_eq!(limiter.lock().unwrap().current_usage(), 4);

arena.shift(3);
assert_eq!(arena.bytes(), &[1]);
assert_eq!(limiter.borrow().current_usage(), 4);
assert_eq!(limiter.lock().unwrap().current_usage(), 4);

arena.append(&[2, 3, 4, 5]).unwrap();
arena.shift(1);
assert_eq!(arena.bytes(), &[2, 3, 4, 5]);
assert_eq!(limiter.borrow().current_usage(), 5);
assert_eq!(limiter.lock().unwrap().current_usage(), 5);
}
}
39 changes: 22 additions & 17 deletions src/memory/limited_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ impl<T> LimitedVec<T> {
}

pub fn push(&mut self, element: T) -> Result<(), MemoryLimitExceededError> {
self.limiter.borrow_mut().increase_usage(size_of::<T>())?;
self.limiter
.lock()
.unwrap()
.increase_usage(size_of::<T>())?;
self.vec.push(element);
Ok(())
}
Expand Down Expand Up @@ -65,7 +68,8 @@ impl<T> LimitedVec<T> {
};

self.limiter
.borrow_mut()
.lock()
.unwrap()
.decrease_usage(size_of::<T>() * (end - start));

self.vec.drain(range)
Expand All @@ -92,7 +96,8 @@ impl<T> Index<usize> for LimitedVec<T> {
impl<T> Drop for LimitedVec<T> {
fn drop(&mut self) {
self.limiter
.borrow_mut()
.lock()
.unwrap()
.decrease_usage(size_of::<T>() * self.vec.len());
}
}
Expand All @@ -101,33 +106,33 @@ impl<T> Drop for LimitedVec<T> {
mod tests {
use super::super::MemoryLimiter;
use super::*;
use std::rc::Rc;
use std::sync::Arc;

#[test]
fn current_usage() {
{
let limiter = MemoryLimiter::new_shared(10);
let mut vec_u8: LimitedVec<u8> = LimitedVec::new(Rc::clone(&limiter));
let mut vec_u8: LimitedVec<u8> = LimitedVec::new(Arc::clone(&limiter));

vec_u8.push(1).unwrap();
vec_u8.push(2).unwrap();
assert_eq!(limiter.borrow().current_usage(), 2);
assert_eq!(limiter.lock().unwrap().current_usage(), 2);
}

{
let limiter = MemoryLimiter::new_shared(10);
let mut vec_u32: LimitedVec<u32> = LimitedVec::new(Rc::clone(&limiter));
let mut vec_u32: LimitedVec<u32> = LimitedVec::new(Arc::clone(&limiter));

vec_u32.push(1).unwrap();
vec_u32.push(2).unwrap();
assert_eq!(limiter.borrow().current_usage(), 8);
assert_eq!(limiter.lock().unwrap().current_usage(), 8);
}
}

#[test]
fn max_limit() {
let limiter = MemoryLimiter::new_shared(2);
let mut vector: LimitedVec<u8> = LimitedVec::new(Rc::clone(&limiter));
let mut vector: LimitedVec<u8> = LimitedVec::new(Arc::clone(&limiter));

vector.push(1).unwrap();
vector.push(2).unwrap();
Expand All @@ -142,35 +147,35 @@ mod tests {
let limiter = MemoryLimiter::new_shared(1);

{
let mut vector: LimitedVec<u8> = LimitedVec::new(Rc::clone(&limiter));
let mut vector: LimitedVec<u8> = LimitedVec::new(Arc::clone(&limiter));

vector.push(1).unwrap();
assert_eq!(limiter.borrow().current_usage(), 1);
assert_eq!(limiter.lock().unwrap().current_usage(), 1);
}

assert_eq!(limiter.borrow().current_usage(), 0);
assert_eq!(limiter.lock().unwrap().current_usage(), 0);
}

#[test]
fn drain() {
let limiter = MemoryLimiter::new_shared(10);
let mut vector: LimitedVec<u8> = LimitedVec::new(Rc::clone(&limiter));
let mut vector: LimitedVec<u8> = LimitedVec::new(Arc::clone(&limiter));

vector.push(1).unwrap();
vector.push(2).unwrap();
vector.push(3).unwrap();
assert_eq!(limiter.borrow().current_usage(), 3);
assert_eq!(limiter.lock().unwrap().current_usage(), 3);

vector.drain(0..3);
assert_eq!(limiter.borrow().current_usage(), 0);
assert_eq!(limiter.lock().unwrap().current_usage(), 0);

vector.push(1).unwrap();
vector.push(2).unwrap();
vector.push(3).unwrap();
vector.push(4).unwrap();
assert_eq!(limiter.borrow().current_usage(), 4);
assert_eq!(limiter.lock().unwrap().current_usage(), 4);

vector.drain(1..=2);
assert_eq!(limiter.borrow().current_usage(), 2);
assert_eq!(limiter.lock().unwrap().current_usage(), 2);
}
}
11 changes: 5 additions & 6 deletions src/memory/limiter.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use thiserror::Error;

pub type SharedMemoryLimiter = Rc<RefCell<MemoryLimiter>>;
pub type SharedMemoryLimiter = Arc<Mutex<MemoryLimiter>>;

/// An error that occures when rewriter exceedes the memory limit specified in the
/// [`MemorySettings`].
Expand All @@ -20,7 +19,7 @@ pub struct MemoryLimiter {

impl MemoryLimiter {
pub fn new_shared(max: usize) -> SharedMemoryLimiter {
Rc::new(RefCell::new(MemoryLimiter {
Arc::new(Mutex::new(MemoryLimiter {
max,
current_usage: 0,
}))
Expand Down Expand Up @@ -62,7 +61,7 @@ mod tests {
#[test]
fn current_usage() {
let limiter = MemoryLimiter::new_shared(10);
let mut limiter = limiter.borrow_mut();
let mut limiter = limiter.lock().unwrap();

assert_eq!(limiter.current_usage(), 0);

Expand All @@ -86,7 +85,7 @@ mod tests {
)]
fn preallocate() {
let limiter = MemoryLimiter::new_shared(10);
let mut limiter = limiter.borrow_mut();
let mut limiter = limiter.lock().unwrap();

limiter.preallocate(8);
assert_eq!(limiter.current_usage(), 8);
Expand Down
8 changes: 4 additions & 4 deletions src/parser/lexer/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<S: LexemeSink> StateMachineActions for Lexer<S> {
} = lexeme.token_outline
{
self.last_start_tag_name_hash = name_hash;
*ns = self.tree_builder_simulator.borrow().current_ns();
*ns = self.tree_builder_simulator.lock().unwrap().current_ns();
}

match self
Expand Down Expand Up @@ -122,13 +122,13 @@ impl<S: LexemeSink> StateMachineActions for Lexer<S> {

#[inline]
fn create_start_tag(&mut self, _input: &[u8]) {
self.attr_buffer.borrow_mut().clear();
self.attr_buffer.lock().unwrap().clear();

self.current_tag_token = Some(StartTag {
name: Range::default(),
name_hash: LocalNameHash::new(),
ns: Namespace::default(),
attributes: Rc::clone(&self.attr_buffer),
attributes: Arc::clone(&self.attr_buffer),
self_closing: false,
});
}
Expand Down Expand Up @@ -295,7 +295,7 @@ impl<S: LexemeSink> StateMachineActions for Lexer<S> {
#[inline]
fn finish_attr(&mut self, _input: &[u8]) {
if let Some(attr) = self.current_attr.take() {
self.attr_buffer.borrow_mut().push(attr);
self.attr_buffer.lock().unwrap().push(attr);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/parser/lexer/lexeme/token_outline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl Align for TagTokenOutline {
name, attributes, ..
} => {
name.align(offset);
attributes.borrow_mut().align(offset);
attributes.lock().unwrap().align(offset);
}
TagTokenOutline::EndTag { name, .. } => name.align(offset),
}
Expand Down
Loading

0 comments on commit 61d33f9

Please sign in to comment.