desync icon indicating copy to clipboard operation
desync copied to clipboard

Getting Rid of 'static

Open anlumo opened this issue 5 years ago • 1 comments

Hi,

Right now the signature for the future is

pub fn future<TFn, TOutput>(&self, job: TFn) -> impl Future<Output=Result<TOutput, oneshot::Canceled>>+Send
    where   TFn:        'static+Send+for<'a> FnOnce(&'a mut T) -> BoxFuture<'a, TOutput>,
            TOutput:    'static+Send;

However, it should be possible to have this instead:

pub fn future<'a, TFn, TOutput>(&'a self, job: TFn) -> impl 'a + Future<Output=Result<TOutput, oneshot::Canceled>>+Send
    where   TFn:        'a+Send+FnOnce(&'a mut T) -> BoxFuture<'a, TOutput>,
            TOutput:    'a+Send;

because using my_desync.future(…).await makes sure that the Desync stays alive until the passed closure is dropped (either because it was run or because it was canceled).

This would allow using local variables inside the closure passed to the future without capturing them.

Now, I've looked into the desync code and I can see how that's hard to implement, but I created this issue to point out that this would be nice to have in the future (no pun intended).

anlumo avatar Aug 19 '20 13:08 anlumo

Hi, it's been a while but I've finally found some time to implement this. The latest revision on the 0.7.0 branch splits future into future_sync and future_desync. future_sync() has the following declaration:

pub fn future_sync<'a, TFn, TOutput>(&'a self, job: TFn) -> impl 'a+Future<Output=Result<TOutput, oneshot::Canceled>>+Send
where   TFn:        'a+Send+for<'b> FnOnce(&'b mut T) -> BoxFuture<'b, TOutput>,
        TOutput:    'a+Send {

Note the difference here is the lifetime 'b which is how long the data in the Desync is borrowed for. ('b is within 'a and is shorter but Rust can't express this at the moment). This is a slightly annoying limitation: the data is only available while the returned future is running as other tasks on the same queue might be using it in the meantime.

Another difference from the original is that if the returned future is dropped, its execution will be cancelled.

future_desync() is the original implementation. It differs from future_sync() in that its future will complete even if the return value is dropped (so it can be used in situations where an executor is not available), and a 'desync' future can run in the background even if the thread that's awaiting it is blocked.

Logicalshift avatar Nov 20 '20 21:11 Logicalshift