Last active
December 20, 2015 14:59
-
-
Save panzi/6151307 to your computer and use it in GitHub Desktop.
None-working unsafe weakrefs for rust (currently crashes the compiler, later it will crash any program that uses this).
**Don't use this!** This is just an experiment.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use weakref::{Weakref,Weakrefs,Referred}; | |
mod weakref; | |
struct Node { | |
weakrefs: ~Weakrefs<Node>, | |
parent: ~Weakref<Node>, | |
children: ~[~Node], | |
data: ~str | |
} | |
impl Referred for Node { | |
#[inline] | |
fn weakrefs<'a>(&'a mut self) -> &'a mut Weakrefs<Node> { | |
return &mut*self.weakrefs; | |
} | |
} | |
impl Node { | |
#[inline] | |
pub fn new(data: ~str) -> Node { | |
Node { | |
weakrefs: Weakrefs::new(), | |
parent: Weakref::new(None), | |
children: ~[], | |
data: data | |
} | |
} | |
pub fn appendChild(&mut self, mut child: ~Node) { | |
child.parent.set(self); | |
self.children.push(child); | |
} | |
#[inline] | |
pub fn clear(&mut self) { self.children.clear(); } | |
#[inline] | |
pub fn iter<'a>(&'a self) -> std::vec::Items<'a, ~Node> { | |
self.children.iter() | |
} | |
#[inline] | |
pub fn len(&self) -> uint { self.children.len() } | |
#[inline] | |
pub fn get<'a>(&'a mut self, index: uint) -> &'a mut Node { | |
&mut*self.children[index] | |
} | |
pub fn remove(&mut self, index: uint) -> Option<~Node> { | |
match self.children.remove(index) { | |
None => None, | |
Some(mut node) => { | |
node.parent.clear(); | |
return Some(node); | |
} | |
} | |
} | |
pub fn parent<'a>(&'a self) -> Option<&'a Node> { | |
return self.parent.get(); | |
} | |
pub fn mut_parent<'a>(&'a mut self) -> Option<&'a mut Node> { | |
return self.parent.mut_get(); | |
} | |
#[inline] | |
pub fn data<'a>(&'a self) -> &'a str { self.data.as_slice() } | |
fn to_indented_str(&self, nesting: uint) -> ~str { | |
let mut s = ~""; | |
let mut i = 0; | |
while i < nesting { | |
s.push_char('\t'); | |
i += 1; | |
} | |
s.push_str(self.data); | |
s.push_char('\n'); | |
let child_nesting = nesting + 1; | |
for child in self.children.iter() { | |
s.push_str((*child).to_indented_str(child_nesting)); | |
} | |
return s; | |
} | |
} | |
impl ToStr for Node { | |
fn to_str(&self) -> ~str { | |
return self.to_indented_str(0); | |
} | |
} | |
impl Drop for Node { | |
fn drop(&mut self) { | |
println!("drop {}",self.data); | |
} | |
} | |
fn main() { | |
let mut tree = ~Node::new(~"root"); | |
let mut i = 0; | |
while i < 5 { | |
let node = ~Node::new(format!("child {}",i)); | |
tree.appendChild(node); | |
i += 1; | |
} | |
for child in tree.iter() { | |
println!("{}.{}", match child.parent() { | |
None => "(none)", | |
Some(p) => p.data() | |
}, child.data()); | |
} | |
println!("child count: {}", tree.children.len()); | |
println!("tree? {}", tree.to_str()); | |
let first = tree.remove(0); | |
tree = ~Node::new(~"dummy"); | |
println!("dummy? {}",match first { | |
None => ~"(none)", | |
Some(ref node) => node.to_str() | |
}); | |
println!("{}",match first { | |
None => "(none)", | |
Some(ref node) => match node.parent() { | |
None => "(none)", | |
Some(ref parent) => parent.data() | |
} | |
}); | |
println!("{}",tree.to_str()); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[crate_id="weakref#1.0"]; | |
#[crate_type="lib"]; | |
pub struct Weakref<T> { | |
priv referred: Option<*mut T> | |
} | |
pub struct Weakrefs<T> { | |
priv weakrefs: ~[*mut Weakref<T>] | |
} | |
pub trait Referred { | |
fn weakrefs<'a>(&'a mut self) -> &'a mut Weakrefs<Self>; | |
} | |
impl<T: Referred> Weakrefs<T> { | |
#[inline] | |
pub fn new() -> ~Weakrefs<T> { | |
~Weakrefs { weakrefs: ~[] } | |
} | |
fn register(&mut self, wref: &mut Weakref<T>) { | |
let ptr: *mut Weakref<T> = &mut *wref; | |
match self.weakrefs.position_elem(&ptr) { | |
Some(_) => {}, | |
None => { | |
self.weakrefs.push(ptr); | |
} | |
} | |
} | |
fn unregister(&mut self, wref: &Weakref<T>) { | |
let ptr: *Weakref<T> = &*wref; | |
let mut i = 0; | |
let n = self.weakrefs.len(); | |
while i < n { | |
unsafe { | |
let mutref = self.weakrefs[i]; | |
let mywref: *Weakref<T> = &*mutref; | |
if mywref == ptr { | |
(*mutref).clear(); | |
self.weakrefs.remove(i); | |
return; | |
} | |
i += 1; | |
} | |
} | |
} | |
} | |
#[unsafe_destructor] | |
impl<T: Referred> Drop for Weakrefs<T> { | |
fn drop(&mut self) { | |
for wref in self.weakrefs.iter() { | |
unsafe { (**wref).referred = None; } | |
} | |
} | |
} | |
impl<T: Referred> Weakref<T> { | |
#[inline] | |
pub fn new(referred: Option<&mut T>) -> ~Weakref<T> { | |
match referred { | |
Some(referred) => { | |
let ptr: *mut T = &mut *referred; | |
let mut wref = ~Weakref { referred: Some(ptr) }; | |
referred.weakrefs().register(wref); | |
return wref; | |
}, | |
None => { | |
return ~Weakref { referred: None }; | |
} | |
} | |
} | |
pub fn set<'a>(&'a mut self, referred: &mut T) -> Option<&'a mut T> { | |
let ptr: *mut T = &mut *referred; | |
let ret = match self.referred { | |
Some(referred) => unsafe { | |
self.referred = None; | |
(*referred).weakrefs().unregister(self); | |
Some(&mut*referred) | |
}, | |
None => None | |
}; | |
self.referred = Some(ptr); | |
referred.weakrefs().register(self); | |
return ret; | |
} | |
pub fn clear(&mut self) { | |
match self.referred { | |
Some(referred) => unsafe { | |
self.referred = None; | |
(*referred).weakrefs().unregister(self); | |
}, | |
None => {} | |
} | |
} | |
/** | |
* WARNING: The lifetime of the returned reference might be wrong. | |
*/ | |
pub fn get<'a>(&'a self) -> Option<&'a T> { | |
match self.referred { | |
Some(referred) => unsafe { return Some(&*referred); }, | |
None => { return None; } | |
} | |
} | |
/** | |
* WARNING: The lifetime of the returned reference might be wrong. | |
*/ | |
pub fn mut_get<'a>(&'a mut self) -> Option<&'a mut T> { | |
match self.referred { | |
Some(referred) => unsafe { return Some(&mut*referred); }, | |
None => { return None; } | |
} | |
} | |
} | |
#[unsafe_destructor] | |
impl<T: Referred> Drop for Weakref<T> { | |
fn drop(&mut self) { | |
match self.referred { | |
Some(referred) => unsafe { | |
(*referred).weakrefs().unregister(self); | |
}, | |
None => {} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment