|
|
|
|
|
by Diggsey
2612 days ago
|
|
I can't speak to every issue which the author might have encountered, but there is a better solution to the lifetime management problem than the two mentioned in the article. Instead of this: fn some_wlroots_callback(output_handle: OutputHandle,
surface_handle: SurfaceHandle) {
output_handle.run(|output| {
surface_handle.run(|surface| {
// maybe some more nested layers...
}).unwrap()
}).unwrap()
}
One can do this: fn some_wlroots_callback(
ctx: CallbackContext,
output_handle: OutputHandle,
surface_handle: SurfaceHandle
) {
let output = ctx.get(output_handle);
let surface = ctx.get(surface_handle);
}
This is safe, because the lifetime of "output" and "surface" can be bound to the lifetime of the "ctx" (whose lifetime is controlled by the library: the library simply has to make sure that "ctx" is not accessible outside of a callback).edit:
Realised you can't tell that there's an implicit lifetime in `CallbackContext` here: struct CallbackContext<'a> { ... };
OR type CallbackContext<'a> = &'a CallbackContextImpl;
|
|
The problem with that design (which is a great design given what I presented in the article by the way!) is that it doesn't allow you to share handles across callbacks, which is mandatory to do anything interesting. I'm assuming here that you can't use the handles except for that callback context. If you can, then that presents a different problem.
https://play.rust-lang.org/?version=stable&mode=debug&editio...
If you can own a context, even with a lifetime parameter it's possible to leak it using the Box api. That allows you to have access to a &'static CallbackContext. This will break that assumption that it only lives as long as the callback itself.