Skip to content

Commit d7fe8c3

Browse files
committed
refactor(headers): switch from MuCell to OptCell
It turns out, we don't need capabilities of MuCell (or even RefCell). We don't to have sophisticated interior mutability. We don't ever lend out references that may be mutated later. Instead, if there is no value to lend, then we generate the value, require interior mutability to save the value internally, and then we return a reference. We never ever change a value once it's been generated. It can be changed, but only via &mut self methods, where we can safely reason about mutability. This means we don't need keep borrow checking code at runtime, which helps performance. We also are able to reduce the amount of unsafe transmutes. The internal API more safely constrains the usage of unsafe, enforcing our invariants, instead of shotgunning unsafe usage with Refs and promising we're doing it correctly. On a machine with lower memory (1GB): Before: test bench_mock_hyper ... bench: 251772 ns/iter (+/- 128445) After: test bench_mock_hyper ... bench: 152603 ns/iter (+/- 25928) On a machine with more memory, weaker CPU: Before: test bench_mock_hyper ... bench: 129398 ns/iter (+/- 51740) After: test bench_mock_hyper ... bench: 115935 ns/iter (+/- 28555) Closes #252
1 parent e9af13c commit d7fe8c3

File tree

4 files changed

+136
-61
lines changed

4 files changed

+136
-61
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ keywords = ["http", "hyper", "hyperium"]
1515
cookie = "*"
1616
log = ">= 0.2.0"
1717
mime = "*"
18-
mucell = "*"
1918
openssl = "*"
2019
rustc-serialize = "*"
2120
time = "*"

src/header/cell.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use std::cell::UnsafeCell;
2+
use std::ops::Deref;
3+
4+
pub struct OptCell<T>(UnsafeCell<Option<T>>);
5+
6+
impl<T> OptCell<T> {
7+
#[inline]
8+
pub fn new(val: Option<T>) -> OptCell<T> {
9+
OptCell(UnsafeCell::new(val))
10+
}
11+
12+
#[inline]
13+
pub fn set(&self, val: T) {
14+
unsafe {
15+
let opt = self.0.get();
16+
debug_assert!((*opt).is_none());
17+
*opt = Some(val)
18+
}
19+
}
20+
21+
#[inline]
22+
pub unsafe fn get_mut(&mut self) -> &mut T {
23+
let opt = &mut *self.0.get();
24+
opt.as_mut().unwrap()
25+
}
26+
}
27+
28+
impl<T> Deref for OptCell<T> {
29+
type Target = Option<T>;
30+
#[inline]
31+
fn deref<'a>(&'a self) -> &'a Option<T> {
32+
unsafe { &*self.0.get() }
33+
}
34+
}
35+
36+
impl<T: Clone> Clone for OptCell<T> {
37+
#[inline]
38+
fn clone(&self) -> OptCell<T> {
39+
OptCell::new((**self).clone())
40+
}
41+
}

0 commit comments

Comments
 (0)