Is there any way to efficiently force Drop order of struct fields? or a workaround?
I know that Drop order is currently undefined in Rust (https://github.com/rust-lang/rfcs/issues/744), but I need to make sure that fields get dropped in certain order, because I'm using a C library that will not get cleaned up properly otherwise.
example:
struct Foo {
a:A,
b:B,
c:C,
}
I want to make sure fields get dropped in order C,B,A.
Not A,B,C, like how Rust seems to do (most of the time), which will break cleanup functions for B and C.
The only safe solution I have found so far is to wrap all fields in Option and then call x.take()'s in Drop to force the drop order, but that is pretty silly.
I'm only guessing, but I'm assuming it is because C requires B and A, and B requires A (simplified)? If so, you might be able to wrap it in types for different states of construction/destruction:
There might be better names for your situation. And of course, it might turn out to be more sillier for your case than the Option<T> variant. Plus it's monday and I might be missing something.
I'm bit doubtful this works.
Since the drop order is undefined, StateB for example could drop state_a before b.
This would mean that a gets dropped before b. Right?
I'm using rust-sdl2 (https://github.com/AngryLawyer/rust-sdl2).
I want to store different SDL handles on a single struct so that i don't have to pass multiple context parameters to functions that need access to them.
Code looks like this
pub struct Context {
pub sdl: sdl2::Sdl,
pub video: sdl2::VideoSubsystem, // depends on sdl
pub renderer: sdl2::render::Renderer<'static>, // depends on video
pub event_pump: sdl2::EventPump, // depends on sdl
.. // other handles for sdl_mixer etc.
}
impl Context {
pub fn new() -> Result<Context, String> {
..
let sdl = sdl2::init().unwrap();
let video = sdl.video().unwrap();
..
let mut renderer = window.renderer().build().unwrap();
..
Ok(Context{ sdl:sdl, video:video, renderer:renderer })
}
}
Now, I suppose I could store borrow references in the struct as well, but then the user would have to initialize SDL and pass the references himself.
Unfortunatelly std::mem::drop won't help here, because you can't drop fields of a mutable reference.
@fzzy you can store references in the Context and still avoid
the user would have to initialize SDL and pass the references himself.
If you use a closure based API
fn withContext<F>(
callback: F // user creates the callback
)
where F: FnOnce(&mut Context)
{
let sdl = ...;
let video = ...;
let ctx = Context { video: &mut video, sdl: &mut sdl, ...};
callback(&mut ctx);
}
Alternatively, you can use a by-value Context and require the user to call a special cleanup function:
[quote="fzzy, post:1, topic:6203"]
I need to make sure that fields get dropped in certain order, because I'm using a C library that will not get cleaned up properly otherwise.
[/quote]Are you certain of this? This would be a bug in the bindings. After looking at rust-sdl2 sources it seems they go to lengths to make sure cleanup is performed in correct order.