Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
syncathetic
Oct 21, 2010
Why not this?
code:

    fn subdivide_voxel<D>(&mut self, deregister_voxel: &D) where D : Fn(u32) {
        *self = match self {
            &mut SVO::Voxel{ ref external_id, voxel_type } => {
                for voxel_id in external_id.get() {
                    deregister_voxel(voxel_id)
                };
                SVO::new_octants([voxel_type, voxel_type, voxel_type, voxel_type,
                                  voxel_type, voxel_type, voxel_type, voxel_type])
            },
            _ => panic!("subdivide_voxel called on a non-voxel!")
        }

Adbot
ADBOT LOVES YOU

syncathetic
Oct 21, 2010
I think your problem comes from Iterator::map being lazy. If the the code in your post could be executed, the code inside the closure would never run. If you want to append something to vec after the closure is evaluated and still use its result, you need to do something like:

code:
fn with_vec(vec: &mut Vec<u8>) {
    let octant_indices = Vec::from_iter(octants.iter().map(|octant| {
        vec.add(???);
        vec.len() as u64 - 1
    }));

    vec.add(???);

    for octant_index in octant_indices {
        //....
    }
}

syncathetic
Oct 21, 2010
I was able to get it to compile making the following changes:

code:
diff --git a/carved_rust/src/svo/generator/height_map.rs b/carved_rust/src/svo/generator/height_map.rs
index 000291a..f3d2bd9 100644
--- a/carved_rust/src/svo/generator/height_map.rs
+++ b/carved_rust/src/svo/generator/height_map.rs
@@ -34,7 +34,7 @@ impl<'a> SubImage<'a> {
 		self.y_n - self.y_0
 	}
 
-	fn rect(&self, x_0: u32, x_n: u32, y_0: u32, y_n: u32) -> SubImage {
+	fn rect(&self, x_0: u32, x_n: u32, y_0: u32, y_n: u32) -> SubImage<'a> {
 		SubImage { x_0: x_0, x_n: x_n, y_0: y_0, y_n: y_n, .. *self }
 	}
 
@@ -51,7 +51,7 @@ impl<'a> SubImage<'a> {
 		Some([ll, lr, rl, rr])
 	}
 
-	fn split_threshold(&'a self) -> Option<[SubImage<'a>; 2]> {
+	fn split_threshold(&self) -> Option<[SubImage<'a>; 2]> {
 		let half_range = (self.b_n - self.b_0) / 2;
 		if half_range == 0 { return None; }
 
@@ -113,4 +113,4 @@ impl SVO {
 			//SVO::Octants([])
 		}
 	}
-}
\ No newline at end of file
+}
I can't really explain why that works, though. I'm pretty sure doing &'a self is generally counter-productive. Most of the time, 'a needs to outlive self to make sense.

syncathetic
Oct 21, 2010
I have an awful suggestion: use mem::transmute to avoid copying altogether. There are a lot of potential problems (it could cause bugs to appear if the structure of SVO changes later), but I don't think there is a faster option.

code:
use std::mem;
use std::marker::PhantomData;

#[derive(Debug, PartialEq, Copy, Clone)]
pub struct Registered;
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct Unregistered;

pub trait RegistrationTrait {}
impl RegistrationTrait for Registered {}
impl RegistrationTrait for Unregistered {}

enum SVO<R: RegistrationTrait> {
    Voxel {
        external_id: u32, // Moved external_id from registration
        data: u32, // Placeholder data type
        phantom: PhantomData<R>,
    },
    Octants([Box<SVO<R>>; 8]),
}


pub trait Deregister: Fn(u32) {}

impl SVO<Registered> {
    fn deregister_inner<D: Deregister>(&self, deregister_voxel: &D) {
        match self {
            &SVO::Voxel { external_id, .. } => deregister_voxel(external_id),
            &SVO::Octants (ref octants) => {
                for c in octants.iter() {
                    c.deregister_inner(deregister_voxel)
                }
            },
        }
    }
    
    pub fn deregister<D: Deregister>(self, deregister_voxel: &D) -> SVO<Unregistered> {
        self.deregister_inner(deregister_voxel);
        unsafe {
            mem::transmute(self)
        }
    }
}

syncathetic
Oct 21, 2010
Could you explain what BindFunc and Registery::binders are?

Edit:
I don't totally understand what you're going for, but this is how I would go about implementing a global registry:
code:
#[macro_use]
extern crate lazy_static;

extern crate toml;

//use message::Message;
struct Message;

use std::error::Error;
use std::collections::HashMap;
use std::sync::RwLock;

trait Decoder: Send + Sync {
    fn decode(&self, data: Vec<u8>) -> Result<Message, Box<Error>>;
}

//type BindFunc = fn(toml::Value) -> Result<Box<Decoder>, Box<Error>>;

struct Registry {
    decoders: HashMap<String, usize>,
    defaults: HashMap<String, usize>,
    //binders: Mutex<HashMap<String, BindFunc>>,

    decoders_cache: Vec<Box<Decoder>>,
}

impl Registry {
    fn new() -> Registry {
        Registry {
            decoders: HashMap::new(),
            defaults: HashMap::new(),
            decoders_cache: Vec::new(),
            //binders: Mutex::new(HashMap::new()),
        }
    }

    pub fn lookup_decoder(&self, name: &str) -> Option<&Decoder> {
        self.decoders.get(name).map(|i| &*self.decoders_cache[*i])
    }

    pub fn lookup_default(&self, name: &str) -> Option<&Decoder> {
        self.defaults.get(name).map(|i| &*self.decoders_cache[*i])
    }

    /*pub fn register(&self, name: String, b: BindFunc) {
        let mut bs = self.binders.lock().unwrap();
        let _ = bs.insert(name, b);
    }*/
}


lazy_static! {
    static ref REGISTRY: RwLock<Registry> = RwLock::new(Registry::new());
}


fn do_nothing(decoder: &Decoder) {
}

fn main() {
    {
        let r = REGISTRY.write().unwrap();
        // Insert decoders here
    }
    {
        let r = REGISTRY.read().unwrap();
        let decoder = r.lookup_decoder("json").unwrap();
        do_nothing(decoder);
    }
}

syncathetic fucked around with this message at 09:05 on Apr 24, 2016

syncathetic
Oct 21, 2010

Jo posted:

Doesn't seem like it. :( When I pulled the node as a value it just complained about moving out of the indexed context.

That error happens because indexing technically returns a value, but you can't move out of a reference. (There are a couple of ways to fix that particular error https://is.gd/nj33No ).

What I think rjmccall was suggesting was something like:

code:
let op = self.nodes[node_id].operation.clone();
match op {
    // ...
}
This way, self isn't borrowed during the body of the match. Obviously, this only makes sense if an operation is inexpensive to clone.

If you're memorizing, it might make sense for get_derivative to borrow self immutably and wrap the hashmap(s) in a RefCell. If the semantic value of the graph isn't changing, interior mutability may be justified.

syncathetic fucked around with this message at 07:23 on Aug 19, 2016

syncathetic
Oct 21, 2010
I don't think its possible for the first case to be null-pointer optimized. Consider https://is.gd/HtdE2R . What value/address does list_end return if the final Empty value isn't on the heap?

As I understand it, Option<bool> having a size of 1 byte might be a breaking change for unsafe code. It would mean that you can no longer blindly memcpy a value onto a &mut bool for fear of clobbering the Option data in the higher bits. I could be wrong though. The exact rules for what is valid unsafe code aren't exactly clear.

Adbot
ADBOT LOVES YOU

syncathetic
Oct 21, 2010
I was going to make the same suggestion, except with a macro https://gist.github.com/anonymous/81b4b2dde02467feb13bc8c2de671ded

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply