So the mutable aliasing in Tracer properly.

Apparently this is what UnsafeCell is for, and the code I wrote
before wasn't technically correct, even thought it worked in
practice.  Hooray for doing things properly!
This commit is contained in:
Nathan Vegdahl 2016-03-21 01:08:19 -07:00
parent e747d7fee8
commit b58ba10f9b

View File

@ -1,5 +1,6 @@
use std::iter; use std::iter;
use std::slice; use std::slice;
use std::cell::UnsafeCell;
use math::Matrix4x4; use math::Matrix4x4;
use assembly::{Assembly, Object}; use assembly::{Assembly, Object};
@ -8,7 +9,7 @@ use surface::SurfaceIntersection;
pub struct Tracer<'a> { pub struct Tracer<'a> {
root: &'a Assembly, root: &'a Assembly,
rays: Vec<Ray>, // Should only be used from trace(), not any other methods rays: UnsafeCell<Vec<Ray>>, // Should only be used from trace(), not any other methods
xform_stack: Vec<Matrix4x4>, xform_stack: Vec<Matrix4x4>,
isects: Vec<SurfaceIntersection>, isects: Vec<SurfaceIntersection>,
} }
@ -18,16 +19,19 @@ impl<'a> Tracer<'a> {
Tracer { Tracer {
root: assembly, root: assembly,
xform_stack: Vec::new(), xform_stack: Vec::new(),
rays: Vec::new(), rays: UnsafeCell::new(Vec::new()),
isects: Vec::new(), isects: Vec::new(),
} }
} }
pub fn trace<'b>(&'b mut self, wrays: &[Ray]) -> &'b [SurfaceIntersection] { pub fn trace<'b>(&'b mut self, wrays: &[Ray]) -> &'b [SurfaceIntersection] {
// Ready the rays // Ready the rays
self.rays.clear(); let rays_ptr = self.rays.get();
self.rays.reserve(wrays.len()); unsafe {
self.rays.extend(wrays.iter()); (*rays_ptr).clear();
(*rays_ptr).reserve(wrays.len());
(*rays_ptr).extend(wrays.iter());
}
// Ready the isects // Ready the isects
self.isects.clear(); self.isects.clear();
@ -44,7 +48,7 @@ impl<'a> Tracer<'a> {
// NOT be used in any other methods. The rays should only be // NOT be used in any other methods. The rays should only be
// accessed in other methods via the mutable slice passed directly // accessed in other methods via the mutable slice passed directly
// to them in their function parameters. // to them in their function parameters.
slice::from_raw_parts_mut(self.rays.as_mut_ptr(), self.rays.len()) &mut (*rays_ptr)[..]
}; };
self.trace_assembly(self.root, wrays, ray_refs); self.trace_assembly(self.root, wrays, ray_refs);