aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/layout/flow_ref.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2014-06-28 08:12:34 -0400
committerJosh Matthews <josh@joshmatthews.net>2014-06-28 08:12:34 -0400
commit23968efbd187de0bf19e766fd3fea8eebe432172 (patch)
tree59886fd2bcfe79870dd0932d7b093630e41355a1 /src/components/layout/flow_ref.rs
parent9f915e9e42217c09c7ed15b14b66fc8f84e38490 (diff)
downloadservo-23968efbd187de0bf19e766fd3fea8eebe432172.tar.gz
servo-23968efbd187de0bf19e766fd3fea8eebe432172.zip
Split layout code into a separate crate.
Diffstat (limited to 'src/components/layout/flow_ref.rs')
-rw-r--r--src/components/layout/flow_ref.rs78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/components/layout/flow_ref.rs b/src/components/layout/flow_ref.rs
new file mode 100644
index 00000000000..f17de19c809
--- /dev/null
+++ b/src/components/layout/flow_ref.rs
@@ -0,0 +1,78 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/// Reference-counted pointers to flows.
+///
+/// Eventually, with dynamically sized types in Rust, much of this code will be superfluous.
+
+use flow::Flow;
+use flow;
+
+use std::mem;
+use std::ptr;
+use std::sync::atomics::SeqCst;
+
+#[unsafe_no_drop_flag]
+pub struct FlowRef {
+ vtable: *u8,
+ ptr: *u8,
+}
+
+impl FlowRef {
+ pub fn new(mut flow: Box<Flow>) -> FlowRef {
+ unsafe {
+ let result = {
+ let flow_ref: &mut Flow = flow;
+ mem::transmute(flow_ref)
+ };
+ mem::forget(flow);
+ result
+ }
+ }
+
+ pub fn get<'a>(&'a self) -> &'a Flow {
+ unsafe {
+ mem::transmute_copy(self)
+ }
+ }
+
+ pub fn get_mut<'a>(&'a mut self) -> &'a mut Flow {
+ unsafe {
+ mem::transmute_copy(self)
+ }
+ }
+}
+
+impl Drop for FlowRef {
+ fn drop(&mut self) {
+ unsafe {
+ if self.vtable == ptr::null() {
+ return
+ }
+ if flow::base(self.get()).ref_count().fetch_sub(1, SeqCst) > 1 {
+ return
+ }
+ let flow_ref: FlowRef = mem::replace(self, FlowRef {
+ vtable: ptr::null(),
+ ptr: ptr::null(),
+ });
+ drop(mem::transmute::<FlowRef,Box<Flow>>(flow_ref));
+ self.vtable = ptr::null();
+ self.ptr = ptr::null();
+ }
+ }
+}
+
+impl Clone for FlowRef {
+ fn clone(&self) -> FlowRef {
+ unsafe {
+ drop(flow::base(self.get()).ref_count().fetch_add(1, SeqCst));
+ FlowRef {
+ vtable: self.vtable,
+ ptr: self.ptr,
+ }
+ }
+ }
+}
+