bumpframe.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use crate::innerlude::*;
  2. use bumpalo::Bump;
  3. use std::cell::Cell;
  4. pub struct ActiveFrame {
  5. // We use a "generation" for users of contents in the bump frames to ensure their data isn't broken
  6. pub generation: Cell<usize>,
  7. // The double-buffering situation that we will use
  8. pub frames: [BumpFrame; 2],
  9. }
  10. pub struct BumpFrame {
  11. pub bump: Bump,
  12. pub(crate) head_node: VNode<'static>,
  13. // used internally for debugging
  14. _name: &'static str,
  15. }
  16. impl ActiveFrame {
  17. pub fn new() -> Self {
  18. let frame_a = BumpFrame {
  19. bump: Bump::new(),
  20. head_node: NodeFactory::unstable_place_holder(),
  21. _name: "wip",
  22. };
  23. let frame_b = BumpFrame {
  24. bump: Bump::new(),
  25. head_node: NodeFactory::unstable_place_holder(),
  26. _name: "fin",
  27. };
  28. Self {
  29. generation: 0.into(),
  30. frames: [frame_a, frame_b],
  31. }
  32. }
  33. pub unsafe fn reset_wip_frame(&mut self) {
  34. self.wip_frame_mut().bump.reset()
  35. }
  36. pub fn update_head_node<'a>(&mut self, node: VNode<'a>) {
  37. self.wip_frame_mut().head_node = unsafe { std::mem::transmute(node) };
  38. }
  39. /// The "work in progress frame" represents the frame that is currently being worked on.
  40. pub fn wip_frame(&self) -> &BumpFrame {
  41. match self.generation.get() & 1 == 0 {
  42. true => &self.frames[0],
  43. false => &self.frames[1],
  44. }
  45. }
  46. pub fn wip_frame_mut(&mut self) -> &mut BumpFrame {
  47. match self.generation.get() & 1 == 0 {
  48. true => &mut self.frames[0],
  49. false => &mut self.frames[1],
  50. }
  51. }
  52. /// The finished frame represents the frame that has been "finished" and cannot be modified again
  53. pub fn finished_frame(&self) -> &BumpFrame {
  54. match self.generation.get() & 1 == 1 {
  55. true => &self.frames[0],
  56. false => &self.frames[1],
  57. }
  58. }
  59. pub fn finished_frame_mut(&mut self) -> &mut BumpFrame {
  60. match self.generation.get() & 1 == 1 {
  61. true => &mut self.frames[0],
  62. false => &mut self.frames[1],
  63. }
  64. }
  65. /// Give out our self-referential item with our own borrowed lifetime
  66. pub fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
  67. let cur_head = &self.finished_frame().head_node;
  68. unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
  69. }
  70. /// Give out our self-referential item with our own borrowed lifetime
  71. pub fn wip_head<'b>(&'b self) -> &'b VNode<'b> {
  72. let cur_head = &self.wip_frame().head_node;
  73. unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
  74. }
  75. pub fn cycle_frame(&mut self) {
  76. self.generation.set(self.generation.get() + 1);
  77. }
  78. }
  79. #[cfg(test)]
  80. mod tests {
  81. //! These tests are bad. I don't have a good way of properly testing the ActiveFrame stuff
  82. use super::*;
  83. #[test]
  84. fn test_bump_frame() {
  85. let mut frames = ActiveFrame::new();
  86. // just cycle a few times and make sure we get the right frames out
  87. for _ in 0..5 {
  88. let fin = frames.finished_frame();
  89. let wip = frames.wip_frame();
  90. assert_eq!(wip._name, "wip");
  91. assert_eq!(fin._name, "fin");
  92. frames.cycle_frame();
  93. let fin = frames.finished_frame();
  94. let wip = frames.wip_frame();
  95. assert_eq!(wip._name, "fin");
  96. assert_eq!(fin._name, "wip");
  97. frames.cycle_frame();
  98. }
  99. assert_eq!(frames.generation.get(), 10);
  100. }
  101. }