Skip to content

Instantly share code, notes, and snippets.

@panzi
Last active December 20, 2015 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panzi/6151307 to your computer and use it in GitHub Desktop.
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.
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());
}
#[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