better safe shared layout cache (#62)

This commit is contained in:
Conrad Ludgate 2023-03-12 12:53:30 +00:00 committed by GitHub
parent 0dc39434c2
commit 02573b0ad2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 12 deletions

View file

@ -1,6 +1,7 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc;
use cassowary::strength::{MEDIUM, REQUIRED, WEAK}; use cassowary::strength::{MEDIUM, REQUIRED, WEAK};
use cassowary::WeightedRelation::*; use cassowary::WeightedRelation::*;
@ -68,8 +69,9 @@ pub struct Layout {
expand_to_fill: bool, expand_to_fill: bool,
} }
type Cache = HashMap<(Rect, Layout), Rc<[Rect]>>;
thread_local! { thread_local! {
static LAYOUT_CACHE: RefCell<HashMap<(Rect, Layout), Vec<Rect>>> = RefCell::new(HashMap::new()); static LAYOUT_CACHE: RefCell<Cache> = RefCell::new(HashMap::new());
} }
impl Default for Layout { impl Default for Layout {
@ -139,8 +141,8 @@ impl Layout {
/// height: 10, /// height: 10,
/// }); /// });
/// assert_eq!( /// assert_eq!(
/// chunks, /// chunks[..],
/// vec![ /// [
/// Rect { /// Rect {
/// x: 2, /// x: 2,
/// y: 2, /// y: 2,
@ -166,8 +168,8 @@ impl Layout {
/// height: 2, /// height: 2,
/// }); /// });
/// assert_eq!( /// assert_eq!(
/// chunks, /// chunks[..],
/// vec![ /// [
/// Rect { /// Rect {
/// x: 0, /// x: 0,
/// y: 0, /// y: 0,
@ -183,7 +185,7 @@ impl Layout {
/// ] /// ]
/// ); /// );
/// ``` /// ```
pub fn split(&self, area: Rect) -> Vec<Rect> { pub fn split(&self, area: Rect) -> Rc<[Rect]> {
// TODO: Maybe use a fixed size cache ? // TODO: Maybe use a fixed size cache ?
LAYOUT_CACHE.with(|c| { LAYOUT_CACHE.with(|c| {
c.borrow_mut() c.borrow_mut()
@ -194,7 +196,7 @@ impl Layout {
} }
} }
fn split(area: Rect, layout: &Layout) -> Vec<Rect> { fn split(area: Rect, layout: &Layout) -> Rc<[Rect]> {
let mut solver = Solver::new(); let mut solver = Solver::new();
let mut vars: HashMap<Variable, (usize, usize)> = HashMap::new(); let mut vars: HashMap<Variable, (usize, usize)> = HashMap::new();
let elements = layout let elements = layout
@ -202,11 +204,13 @@ fn split(area: Rect, layout: &Layout) -> Vec<Rect> {
.iter() .iter()
.map(|_| Element::new()) .map(|_| Element::new())
.collect::<Vec<Element>>(); .collect::<Vec<Element>>();
let mut results = layout let mut res = layout
.constraints .constraints
.iter() .iter()
.map(|_| Rect::default()) .map(|_| Rect::default())
.collect::<Vec<Rect>>(); .collect::<Rc<[Rect]>>();
let mut results = Rc::get_mut(&mut res).expect("newly created Rc should have no shared refs");
let dest_area = area.inner(&layout.margin); let dest_area = area.inner(&layout.margin);
for (i, e) in elements.iter().enumerate() { for (i, e) in elements.iter().enumerate() {
@ -343,7 +347,7 @@ fn split(area: Rect, layout: &Layout) -> Vec<Rect> {
} }
} }
} }
results res
} }
/// A container used by the solver inside split /// A container used by the solver inside split

View file

@ -280,7 +280,7 @@ impl<'a> Table<'a> {
if !self.widths.is_empty() { if !self.widths.is_empty() {
constraints.pop(); constraints.pop();
} }
let mut chunks = Layout::default() let chunks = Layout::default()
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.constraints(constraints) .constraints(constraints)
.expand_to_fill(false) .expand_to_fill(false)
@ -290,8 +290,9 @@ impl<'a> Table<'a> {
width: max_width, width: max_width,
height: 1, height: 1,
}); });
let mut chunks = &chunks[..];
if has_selection { if has_selection {
chunks.remove(0); chunks = &chunks[1..];
} }
chunks.iter().step_by(2).map(|c| c.width).collect() chunks.iter().step_by(2).map(|c| c.width).collect()
} }