From 6aaf03a03409cb41f066286706fe0a6de7f8bf52 Mon Sep 17 00:00:00 2001 From: Lars Bergstrom Date: Tue, 18 Feb 2014 17:29:14 -0600 Subject: [PATCH] De @-mut rust-layers. This commit adds a fake temp_rc that doesn't require send/freeze, which will be removed after the Rust upgrade (it is a copy of that Rc).. --- layers.rs | 150 ++++++++++++++++++++++++------------------ lib.rs | 1 + rendergl.rs | 45 ++++++++----- temp_rc.rs | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 80 deletions(-) create mode 100644 temp_rc.rs diff --git a/layers.rs b/layers.rs index 2d5ec23..7746ff8 100644 --- a/layers.rs +++ b/layers.rs @@ -12,23 +12,32 @@ use texturegl::Texture; use geom::matrix::{Matrix4, identity}; use geom::size::Size2D; use geom::rect::Rect; -use std::managed::mut_ptr_eq; +use std::cell::RefCell; +use std::ptr::to_unsafe_ptr; +use temp_rc::Rc; pub enum Format { ARGB32Format, RGB24Format } +#[deriving(Clone)] pub enum Layer { - ContainerLayerKind(@mut ContainerLayer), - TextureLayerKind(@mut TextureLayer), + ContainerLayerKind(Rc), + TextureLayerKind(Rc), } impl Layer { pub fn with_common(&self, f: |&mut CommonLayer| -> T) -> T { match *self { - ContainerLayerKind(container_layer) => f(&mut container_layer.common), - TextureLayerKind(texture_layer) => f(&mut texture_layer.common), + ContainerLayerKind(ref container_layer) => { + let mut tmp = container_layer.borrow().common.borrow_mut(); + f(tmp.get()) + }, + TextureLayerKind(ref texture_layer) => { + let mut tmp = texture_layer.borrow().common.borrow_mut(); + f(tmp.get()) + }, } } } @@ -59,19 +68,19 @@ pub fn CommonLayer() -> CommonLayer { pub struct ContainerLayer { - common: CommonLayer, - first_child: Option, - last_child: Option, - scissor: Option>, + common: RefCell, + first_child: RefCell>, + last_child: RefCell>, + scissor: RefCell>>, } pub fn ContainerLayer() -> ContainerLayer { ContainerLayer { - common: CommonLayer(), - first_child: None, - last_child: None, - scissor: None, + common: RefCell::new(CommonLayer()), + first_child: RefCell::new(None), + last_child: RefCell::new(None), + scissor: RefCell::new(None), } } @@ -81,108 +90,125 @@ struct ChildIterator { impl Iterator for ChildIterator { fn next(&mut self) -> Option { - match self.current { - None => None, - Some(child) => { - self.current = child.with_common(|x| x.next_sibling); - Some(child) - } - } + let (new_current, result) = + match self.current { + None => (None, None), + Some(ref child) => { + (child.with_common(|x| x.next_sibling.clone()), + Some(child.clone())) + } + }; + self.current = new_current; + result } } impl ContainerLayer { pub fn children(&self) -> ChildIterator { - ChildIterator { current: self.first_child } + ChildIterator { current: { + // NOTE: work around borrowchk + let tmp = self.first_child.borrow(); + tmp.get().clone() + } + } } /// Adds a child to the beginning of the list. /// Only works when the child is disconnected from the layer tree. - pub fn add_child_start(@mut self, new_child: Layer) { + pub fn add_child_start(pseudo_self: Rc, new_child: Layer) { new_child.with_common(|new_child_common| { assert!(new_child_common.parent.is_none()); assert!(new_child_common.prev_sibling.is_none()); assert!(new_child_common.next_sibling.is_none()); - new_child_common.parent = Some(ContainerLayerKind(self)); - - match self.first_child { - None => {} - Some(first_child) => { - first_child.with_common(|first_child_common| { - assert!(first_child_common.prev_sibling.is_none()); - first_child_common.prev_sibling = Some(new_child); - new_child_common.next_sibling = Some(first_child); - }); + new_child_common.parent = Some(ContainerLayerKind(pseudo_self.clone())); + + // NOTE: work around borrowchk + { + let tmp = pseudo_self.borrow().first_child.borrow(); + match *tmp.get() { + None => {} + Some(ref first_child) => { + first_child.with_common(|first_child_common| { + assert!(first_child_common.prev_sibling.is_none()); + first_child_common.prev_sibling = Some(new_child.clone()); + new_child_common.next_sibling = Some(first_child.clone()); + }); + } } } - self.first_child = Some(new_child); + pseudo_self.borrow().first_child.set(Some(new_child.clone())); - match self.last_child { - None => self.last_child = Some(new_child), - Some(_) => {} + match pseudo_self.borrow().last_child.borrow().get() { + &None => pseudo_self.borrow().last_child.set(Some(new_child.clone())), + &Some(_) => {} } }); } /// Adds a child to the end of the list. /// Only works when the child is disconnected from the layer tree. - pub fn add_child_end(@mut self, new_child: Layer) { + pub fn add_child_end(pseudo_self: Rc, new_child: Layer) { new_child.with_common(|new_child_common| { assert!(new_child_common.parent.is_none()); assert!(new_child_common.prev_sibling.is_none()); assert!(new_child_common.next_sibling.is_none()); - new_child_common.parent = Some(ContainerLayerKind(self)); - - match self.last_child { - None => {} - Some(last_child) => { - last_child.with_common(|last_child_common| { - assert!(last_child_common.next_sibling.is_none()); - last_child_common.next_sibling = Some(new_child); - new_child_common.prev_sibling = Some(last_child); - }); + new_child_common.parent = Some(ContainerLayerKind(pseudo_self.clone())); + + // NOTE: work around borrowchk + { + let tmp = pseudo_self.borrow().last_child.borrow(); + match *tmp.get() { + None => {} + Some(ref last_child) => { + last_child.with_common(|last_child_common| { + assert!(last_child_common.next_sibling.is_none()); + last_child_common.next_sibling = Some(new_child.clone()); + new_child_common.prev_sibling = Some(last_child.clone()); + }); + } } } - self.last_child = Some(new_child); + pseudo_self.borrow().last_child.set(Some(new_child.clone())); - match self.first_child { - None => self.first_child = Some(new_child), - Some(_) => {} - } + pseudo_self.borrow().first_child.with_mut(|child| + match *child { + Some(_) => {}, + None => *child = Some(new_child.clone()), + }); }); } - pub fn remove_child(@mut self, child: Layer) { + pub fn remove_child(pseudo_self: Rc, child: Layer) { child.with_common(|child_common| { assert!(child_common.parent.is_some()); - match child_common.parent.unwrap() { - ContainerLayerKind(ref container) => { - assert!(mut_ptr_eq(*container, self)); + match child_common.parent { + Some(ContainerLayerKind(ref container)) => { + assert!(to_unsafe_ptr(container.borrow()) == to_unsafe_ptr(pseudo_self.borrow())); }, _ => fail!(~"Invalid parent of child in layer tree"), } match child_common.next_sibling { None => { // this is the last child - self.last_child = child_common.prev_sibling; + pseudo_self.borrow().last_child.set(child_common.prev_sibling.clone()); }, Some(ref sibling) => { sibling.with_common(|sibling_common| { - sibling_common.prev_sibling = child_common.prev_sibling; + sibling_common.prev_sibling = child_common.prev_sibling.clone(); }); } } match child_common.prev_sibling { None => { // this is the first child - self.first_child = child_common.next_sibling; + pseudo_self.borrow().first_child.set(child_common.next_sibling.clone()); }, Some(ref sibling) => { sibling.with_common(|sibling_common| { - sibling_common.next_sibling = child_common.next_sibling; + sibling_common.next_sibling = child_common.next_sibling.clone(); }); } } @@ -200,7 +226,7 @@ pub enum Flip { } pub struct TextureLayer { - common: CommonLayer, + common: RefCell, /// A handle to the GPU texture. texture: Texture, /// The size of the texture in pixels. @@ -212,7 +238,7 @@ pub struct TextureLayer { impl TextureLayer { pub fn new(texture: Texture, size: Size2D, flip: Flip) -> TextureLayer { TextureLayer { - common: CommonLayer(), + common: RefCell::new(CommonLayer()), texture: texture, size: size, flip: flip, diff --git a/lib.rs b/lib.rs index f7cffb7..0c5b86d 100755 --- a/lib.rs +++ b/lib.rs @@ -29,6 +29,7 @@ extern mod egl; pub mod layers; pub mod color; +pub mod temp_rc; pub mod rendergl; pub mod scene; pub mod texturegl; diff --git a/rendergl.rs b/rendergl.rs index 9db6269..ea35983 100755 --- a/rendergl.rs +++ b/rendergl.rs @@ -351,14 +351,14 @@ pub fn bind_and_render_quad(render_context: RenderContext, // Layer rendering pub trait Render { - fn render(@mut self, + fn render(&self, render_context: RenderContext, transform: Matrix4, scene_size: Size2D); } impl Render for layers::ContainerLayer { - fn render(@mut self, + fn render(&self, render_context: RenderContext, transform: Matrix4, scene_size: Size2D) { @@ -370,8 +370,10 @@ impl Render for layers::ContainerLayer { None }; - match self.scissor { - Some(rect) => { + // NOTE: work around borrowchk + let tmp = self.scissor.borrow(); + match tmp.get() { + &Some(rect) => { let size = Size2D((rect.size.width * transform.m11) as GLint, (rect.size.height * transform.m22) as GLint); @@ -426,36 +428,43 @@ impl Render for layers::ContainerLayer { } } } - None => {} // Nothing to do + &None => {} // Nothing to do } - let transform = transform.mul(&self.common.transform); - for child in self.children() { - render_layer(render_context, transform, scene_size, child); + // NOTE: work around borrowchk + { + let tmp = self.common.borrow(); + let transform = transform.mul(&tmp.get().transform); + for child in self.children() { + render_layer(render_context, transform, scene_size, child); + } } - - match (self.scissor, old_rect_opt) { - (Some(_), Some(old_rect)) => { + + // NOTE: work around borrowchk + let tmp = self.scissor.borrow(); + match (tmp.get(), old_rect_opt) { + (&Some(_), Some(old_rect)) => { // Set scissor back to the parent's scissoring rect. scissor(old_rect.origin.x, old_rect.origin.y, old_rect.size.width as GLsizei, old_rect.size.height as GLsizei); } - (Some(_), None) => { + (&Some(_), None) => { // Our parents are not being scissored, so disable scissoring for now disable(SCISSOR_TEST); } - (None, _) => {} // Nothing to do + (&None, _) => {} // Nothing to do } } } impl Render for layers::TextureLayer { - fn render(@mut self, + fn render(&self, render_context: RenderContext, transform: Matrix4, scene_size: Size2D) { - let transform = transform.mul(&self.common.transform); + let tmp = self.common.borrow(); + let transform = transform.mul(&tmp.get().transform); bind_and_render_quad(render_context, &self.texture, self.flip, &transform, scene_size); } } @@ -466,10 +475,10 @@ fn render_layer(render_context: RenderContext, layer: layers::Layer) { match layer { ContainerLayerKind(container_layer) => { - container_layer.render(render_context, transform, scene_size) + container_layer.borrow().render(render_context, transform, scene_size) } TextureLayerKind(texture_layer) => { - texture_layer.render(render_context, transform, scene_size) + texture_layer.borrow().render(render_context, transform, scene_size) } } } @@ -489,7 +498,7 @@ pub fn render_scene(render_context: RenderContext, scene: &Scene) { let transform = scene.transform; // Render the root layer. - render_layer(render_context, transform, scene.size, scene.root); + render_layer(render_context, transform, scene.size, scene.root.clone()); } #[cfg(debug)] diff --git a/temp_rc.rs b/temp_rc.rs new file mode 100644 index 0000000..221ec95 --- /dev/null +++ b/temp_rc.rs @@ -0,0 +1,184 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! Task-local reference-counted boxes (`Rc` type) + +The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and +will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the +overhead of atomic reference counting. + +The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak` +pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been +freed. + +For example, a tree with parent pointers can be represented by putting the nodes behind `Strong` +pointers, and then storing the parent pointers as `Weak` pointers. + +*/ + +use std::cast::transmute; +use std::ops::Drop; +use std::cmp::{Eq, Ord}; +use std::clone::{Clone, DeepClone}; +use std::rt::global_heap::exchange_free; +use std::ptr::read_ptr; +use std::option::{Option, Some, None}; + +struct RcBox { + value: T, + strong: uint, + weak: uint +} + +/// Immutable reference counted pointer type +#[unsafe_no_drop_flag] +pub struct Rc { + priv ptr: *mut RcBox, +} + +impl Rc { + /// Construct a new reference-counted box + pub fn new(value: T) -> Rc { + unsafe { + Rc { + // there is an implicit weak pointer owned by all the + // strong pointers, which ensures that the weak + // destructor never frees the allocation while the + // strong destructor is running, even if the weak + // pointer is stored inside the strong one. + ptr: transmute(~RcBox { value: value, strong: 1, weak: 1 }), + } + } + } +} + +impl Rc { + /// Borrow the value contained in the reference-counted box + #[inline(always)] + pub fn borrow<'a>(&'a self) -> &'a T { + unsafe { &(*self.ptr).value } + } + + /// Downgrade the reference-counted pointer to a weak reference + pub fn downgrade(&self) -> Weak { + unsafe { + (*self.ptr).weak += 1; + Weak { ptr: self.ptr } + } + } +} + +#[unsafe_destructor] +impl Drop for Rc { + fn drop(&mut self) { + unsafe { + if self.ptr != 0 as *mut RcBox { + (*self.ptr).strong -= 1; + if (*self.ptr).strong == 0 { + read_ptr(self.borrow()); // destroy the contained object + + // remove the implicit "strong weak" pointer now + // that we've destroyed the contents. + (*self.ptr).weak -= 1; + + if (*self.ptr).weak == 0 { + exchange_free(self.ptr as *i8) + } + } + } + } + } +} + +impl Clone for Rc { + #[inline] + fn clone(&self) -> Rc { + unsafe { + (*self.ptr).strong += 1; + Rc { ptr: self.ptr } + } + } +} + +impl DeepClone for Rc { + #[inline] + fn deep_clone(&self) -> Rc { + Rc::new(self.borrow().deep_clone()) + } +} + +impl Eq for Rc { + #[inline(always)] + fn eq(&self, other: &Rc) -> bool { *self.borrow() == *other.borrow() } + + #[inline(always)] + fn ne(&self, other: &Rc) -> bool { *self.borrow() != *other.borrow() } +} + +impl Ord for Rc { + #[inline(always)] + fn lt(&self, other: &Rc) -> bool { *self.borrow() < *other.borrow() } + + #[inline(always)] + fn le(&self, other: &Rc) -> bool { *self.borrow() <= *other.borrow() } + + #[inline(always)] + fn gt(&self, other: &Rc) -> bool { *self.borrow() > *other.borrow() } + + #[inline(always)] + fn ge(&self, other: &Rc) -> bool { *self.borrow() >= *other.borrow() } +} + +/// Weak reference to a reference-counted box +#[unsafe_no_drop_flag] +pub struct Weak { + priv ptr: *mut RcBox, +} + +impl Weak { + /// Upgrade a weak reference to a strong reference + pub fn upgrade(&self) -> Option> { + unsafe { + if (*self.ptr).strong == 0 { + None + } else { + (*self.ptr).strong += 1; + Some(Rc { ptr: self.ptr }) + } + } + } +} + +#[unsafe_destructor] +impl Drop for Weak { + fn drop(&mut self) { + unsafe { + if self.ptr != 0 as *mut RcBox { + (*self.ptr).weak -= 1; + // the weak count starts at 1, and will only go to + // zero if all the strong pointers have disappeared. + if (*self.ptr).weak == 0 { + exchange_free(self.ptr as *i8) + } + } + } + } +} + +impl Clone for Weak { + #[inline] + fn clone(&self) -> Weak { + unsafe { + (*self.ptr).weak += 1; + Weak { ptr: self.ptr } + } + } +} +