123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- use crate::innerlude::*;
- use bumpalo::Bump;
- use std::cell::Cell;
- pub struct ActiveFrame {
- // We use a "generation" for users of contents in the bump frames to ensure their data isn't broken
- pub generation: Cell<usize>,
- // The double-buffering situation that we will use
- pub frames: [BumpFrame; 2],
- }
- pub struct BumpFrame {
- pub bump: Bump,
- pub(crate) head_node: VNode<'static>,
- // used internally for debugging
- _name: &'static str,
- }
- impl ActiveFrame {
- pub fn new() -> Self {
- let frame_a = BumpFrame {
- bump: Bump::new(),
- head_node: NodeFactory::unstable_place_holder(),
- _name: "wip",
- };
- let frame_b = BumpFrame {
- bump: Bump::new(),
- head_node: NodeFactory::unstable_place_holder(),
- _name: "fin",
- };
- Self {
- generation: 0.into(),
- frames: [frame_a, frame_b],
- }
- }
- pub unsafe fn reset_wip_frame(&mut self) {
- self.wip_frame_mut().bump.reset()
- }
- pub fn update_head_node<'a>(&mut self, node: VNode<'a>) {
- self.wip_frame_mut().head_node = unsafe { std::mem::transmute(node) };
- }
- /// The "work in progress frame" represents the frame that is currently being worked on.
- pub fn wip_frame(&self) -> &BumpFrame {
- match self.generation.get() & 1 == 0 {
- true => &self.frames[0],
- false => &self.frames[1],
- }
- }
- pub fn wip_frame_mut(&mut self) -> &mut BumpFrame {
- match self.generation.get() & 1 == 0 {
- true => &mut self.frames[0],
- false => &mut self.frames[1],
- }
- }
- /// The finished frame represents the frame that has been "finished" and cannot be modified again
- pub fn finished_frame(&self) -> &BumpFrame {
- match self.generation.get() & 1 == 1 {
- true => &self.frames[0],
- false => &self.frames[1],
- }
- }
- pub fn finished_frame_mut(&mut self) -> &mut BumpFrame {
- match self.generation.get() & 1 == 1 {
- true => &mut self.frames[0],
- false => &mut self.frames[1],
- }
- }
- /// Give out our self-referential item with our own borrowed lifetime
- pub fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
- let cur_head = &self.finished_frame().head_node;
- unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
- }
- /// Give out our self-referential item with our own borrowed lifetime
- pub fn wip_head<'b>(&'b self) -> &'b VNode<'b> {
- let cur_head = &self.wip_frame().head_node;
- unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
- }
- pub fn cycle_frame(&mut self) {
- self.generation.set(self.generation.get() + 1);
- }
- }
- #[cfg(test)]
- mod tests {
- //! These tests are bad. I don't have a good way of properly testing the ActiveFrame stuff
- use super::*;
- #[test]
- fn test_bump_frame() {
- let mut frames = ActiveFrame::new();
- // just cycle a few times and make sure we get the right frames out
- for _ in 0..5 {
- let fin = frames.finished_frame();
- let wip = frames.wip_frame();
- assert_eq!(wip._name, "wip");
- assert_eq!(fin._name, "fin");
- frames.cycle_frame();
- let fin = frames.finished_frame();
- let wip = frames.wip_frame();
- assert_eq!(wip._name, "fin");
- assert_eq!(fin._name, "wip");
- frames.cycle_frame();
- }
- assert_eq!(frames.generation.get(), 10);
- }
- }
|