make aux type more generic
Closed this issue · 6 comments
As I see the provided aux type is never used by the graph.
Can we make it more general to let the client decide if it is &mut T, or &T or a "moved" T object ?
In other word make the &mut part of the generic argument:
Graph<Backend, &mut World> instead of Graph<Backend, World>
or Graph<Backend, &World> instead of Graph<Backend, World>
build(aux: T) instead of build(aux: &mut T)
@zpgaal I was thinking about it.
Lets assume that you have created GraphBuilder<B, &'a mut T>
.
Next you call GraphBuilder<B, &'a mut T>::build
and this call borrows T
for entire 'a
.
Now you can't call Graph<B, &'a mut T>::run
because T
is borrowed for 'a
.
Unless you will provide new T
for each call and ensure each one will leave at least as long as Graph
instance or use unsafe code to mess with lifetimes.
If you know how to do the trick with subtypes and allow this to work - please share 😉
Ok i'll try to do some test without any promise :)
Another option could be to make T:Clone and for the current behavior one have to use some kind internal mutability (refcell, arc, mutex, etc.)
Some background info: I' m experimenting with shred (as i remember amethyst also relies on it). And it has its own guards for mut and non-mut handling (like mutex). For rendy I had to encapsulate the resources (world) not to require a mutable capture of the whole state. Though i'm not quite sure how will the update of the systems in shred and graph traverse work together.
Maybe i just have to make rendering part of a system(tasks) and get the required mutable state for the graph.
If you take a look at split
branch you'll see Graph::run
method now takes aux: &T
.
So you will only need mutable access during graph building. I would like to relax that requirement as well, but not figured yet how to do that.
I've tried make the T an argument of the functions, but of course it wont compile (cannot be made into object). I've also tried the Rc/Mutex/Arc combos, it could work but I would not say it is any better.
Another issue is that T must be 'static that prevents to pass any structure with reference.
I think GAT might be a solution, but that's not an option at the moment:
trait Graph<B> {
type Aux<'a>;
fn run<'a>(aux: Aux<'a>);
}
But for now I'm out of ideas that does not involve unsafe.
I think that as it is now Graph
should be useable with specs or shred.
I think we can close it