Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turning reference of Future to Future of reference #4

Open
WaDelma opened this issue Jun 23, 2016 · 9 comments
Open

Turning reference of Future to Future of reference #4

WaDelma opened this issue Jun 23, 2016 · 9 comments
Assignees

Comments

@WaDelma
Copy link

WaDelma commented Jun 23, 2016

Is there a way or can a way be added to to turn &mut Future to Future<&mut T> and the same with shared references?
I have a hash map that maps key to a future. I populate this map in background with threadpool, but in certain situations I want to access future immediately.
So I am using HashMaps entry API to do the processing in the main thread:

fn get(&mut self, key: Key) -> &mut Value { 
    self.map
        .entry(key)
        .or_insert_with(||
            Future::with_value(do_work()))
        .turn_mut_ref_of_future_to_future_of_mut_ref()
        .value()
        .unwrap()
}

Best name for the method would propably be as_mut as that is what Options equivalent method is called.

@jsgf
Copy link
Owner

jsgf commented Jun 28, 2016

Hm, I'll have to think about it. I suspect it will be hard to get right, because of the lifetime of the &mut T references have to outlive the Future, and some Future/Promise methods require the values to have 'static lifetime.

@jsgf
Copy link
Owner

jsgf commented Jun 28, 2016

Further thoughts:

Operations on Future like value consume the Future, so they don't work on a &mut Future. And there's no real way to convert a &mut Future<T> into Future<&mut T>, since that would imply two instances of a Future for a single Promise, which really doesn't fit in with the model. It would also imply that the corresponding Promise has to change type from T to &mut T, which doesn't make sense in Rust's type system.

I think if you have a HashMap<K, Future<T>>, and you want to get the values out, then you need to use the entry API to extract the Future, then either use poll() or value() to get the Future's value. If you're using poll and it returns Pollresult::Unresolved then you can use the entry API to reinsert the Future. If you know the value is actually already resolved, or will be soon, then you can use value(), but effectively you need to remove the Future from the HashMap.

Can you go into a bit more detail about what your actual code is doing?

@WaDelma
Copy link
Author

WaDelma commented Jun 28, 2016

I am trying to create voxel based game engine, where I am generating/loading chunks concurrently. But if something happens that needs to set/get block in a chunk that is not loaded/generated I have to wait for it to do.

So basically I am currently treating Future like permanent container that just might not have the value right now.

@WaDelma
Copy link
Author

WaDelma commented Jun 28, 2016

Actually having method that returns mutable reference to value inside would be enough.

@jsgf
Copy link
Owner

jsgf commented Jun 29, 2016

Yeah, right now you'd need to pull the Future out and put it back, or put the real value back (ie, have some enum type which is either a Future<T> or a T). That's pretty cumbersome.

Changing the Future to return references to its internals is a bit of a design change, but I'll see how much impact it has.

@jsgf jsgf self-assigned this Jun 29, 2016
@jsgf
Copy link
Owner

jsgf commented Jul 5, 2016

I added value_ref() and poll_ref() to get a reference to the value of the Future in change 2484537. I'm not very keen on adding _mut variants of this to allow mutation of the interior of the Future - I think it would be better to use RefCell or something like that as the type if you want to do that.

@WaDelma
Copy link
Author

WaDelma commented Jul 6, 2016

Using RefCell just to get around library limitation sounds unfortunate... And the other option of maintaining two different HashMaps for Futures and the values seems also annoying.

@jsgf
Copy link
Owner

jsgf commented Jul 7, 2016

I don't see it as a limitation. A Future is not supposed to be a mutable box for a value; its specifically the result from a Promise. If you want to add interior mutability, then Rust offers several solutions, each with their own tradeoffs: Cell, RefCell, Mutex, etc. I could make Future be a poor re-implementation of, say, RefCell, but what if you wanted multithreaded access, or something else?

Now that there's the _ref methods, it can be a building block to compose other functionality on top.

@WaDelma
Copy link
Author

WaDelma commented Jul 7, 2016

Maybe I am not seeing the whole picture, but I don't understand what prevents just adding value_mut that works exactly like value_ref, but uses as_mut instead of as_ref.
And as you say the solutions for interior mutability all have tradeoffs, which I don't see there being for value_mut as it just uses borrowck.
Hmm... Maybe I could just create enum that would either be Future or T... That would work.

enum MaybeFuture<T> {
    Future(Future<T>),
    Value(T),
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants