Skip Menu |

This queue is for tickets about the future CPAN distribution.

Report information
The Basics
Id: 107015
Status: resolved
Priority: 0/
Queue: future

People
Owner: Nobody in particular
Requestors: yanick+cpan [...] babyl.dyndns.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: intermediary future lost because of `weaken`
An example shows it best: use Future; use Test::More tests => 1; my $first = Future->new; { $first->then(sub{ Future->new()->done })->on_ready(sub { pass } ); } $first->done; Because of the `weaken` at line 1076 of the module, the `then` future will be lost as soon as we leave the inner scope. I've looked at all the tests in the distribution, and I /think/ that we can do away with that `weaken`.
On Thu Sep 10 14:17:50 2015, YANICK wrote: Show quoted text
> Because of the `weaken` at line 1076 of the module, the `then` future > will be lost as soon as we leave the inner scope. I've looked at all > the tests in the distribution, and I /think/ that we can do away with > that `weaken`.
This is intentional. You have to hold on to the tail-end of a Future chain, or it may well evaporate into thin air and you'll lose it. If the weaken wasn't there, you'd run the risk of easily creating far too many strong-cycle references. We tried that and it leads to mass amounts of memory leak. Best avoided. Any Future you create has to be held onto somehow - either by being the head end into another chain or convergence, calling ->get on it, or being stored strongly by some container system such as IO::Async's ->adopt_future. -- Paul Evans
Subject: Re: [rt.cpan.org #107015] intermediary future lost because of `weaken`
Date: Wed, 18 Nov 2015 10:49:42 -0500
To: bug-future [...] rt.cpan.org
From: Yanick Champoux <yanick [...] babyl.dyndns.org>
Hi! And thanks for answering! :-) On 2015-11-18 09:30 AM, Paul Evans via RT wrote: Show quoted text
> This is intentional. You have to hold on to the tail-end of a Future chain, or it may well evaporate into thin air and you'll lose it. > > If the weaken wasn't there, you'd run the risk of easily creating far too many strong-cycle references. We tried that and it leads to mass amounts of memory leak. Best avoided. > > Any Future you create has to be held onto somehow - either by being the head end into another chain or convergence, calling ->get on it, or being stored strongly by some container system such as IO::Async's ->adopt_future.
I see. Hmmm... For something like my example, do you think the following would be an acceptable way of going about it? use Future; use Test::More tests => 1; my $first = Future->new; sub Future::keep_alive { # take the occasion to do house-keeping and # remove all promises that are done, and thus # don't need to be kept around @Future::KeptAround = grep { not $_->is_ready } @Future::KeptAround, @_; } { $first->then(sub{ Future->new->done })->on_ready(sub{ pass })->keep_alive; } $first->done;
You *could* but that's very messy. Why not return the value of the future up to the caller? Library functions should return future instances up to their callers. If you're right at the toplevel of the program, then you can likely put a trailing ->get call on it, to force the future to resolve now. If you're waiting on a few things all to happen, shove them into a ->needs_all and ->get on that Future->needs_all( func1(), func2(), func3(), )->get; Where each of the funcN() function calls returns a future. -- Paul Evans
Subject: Re: [rt.cpan.org #107015] intermediary future lost because of `weaken`
Date: Wed, 18 Nov 2015 13:28:25 -0500
To: bug-future [...] rt.cpan.org
From: Yanick Champoux <yanick [...] babyl.dyndns.org>
On 2015-11-18 11:35 AM, Paul Evans via RT wrote: Show quoted text
> You *could* but that's very messy. Why not return the value of the future up to the caller?
I could, and I probably will. You're giving me ideas. :-) But yeah, without boring you to tears with the details, I have a RPC client using Beam::Emitter, with code looking like: $self->subscribe( 'file_to_package_name', sub { my $msg = shift; $self->api->vim_call_function( fname => 'expand', args => [ '%:p' ] ) ->then( sub { $self->api->vim_set_current_line( line => 'package ' . file_to_package_name(shift) . ';' ) })->on_done(sub{ $msg->done; }); }); It's just that I am expecting the house-keeping to be done automatically. I.e., if I do $foo->then(sub { ... })->then(sub{ ... }); it'd be neat if it would Just Work(tm) without me having to do my $p = $foo->then(sub { ... })->then(sub{ ... }); and keep `$p` around. But you stirred stuff with `needs_all`. I think I have a plan B that will work. Thanks again! :-)
There are a couple of helper methods/functions around for this type of thing: * https://metacpan.org/pod/Variable::Disposition#retain_future * https://metacpan.org/pod/IO::Async::Notifier#adopt_future Since I think the current behaviour is by design, this can probably be closed. On 2015-11-18 18:28:40, yanick@babyl.dyndns.org wrote: Show quoted text
> On 2015-11-18 11:35 AM, Paul Evans via RT wrote:
> > You *could* but that's very messy. Why not return the value of the > > future up to the caller?
> > I could, and I probably will. You're giving me ideas. :-) > > But yeah, without boring you to tears with the details, I have a RPC > client using Beam::Emitter, with code looking like: > > $self->subscribe( 'file_to_package_name', sub { > my $msg = shift; > > $self->api->vim_call_function( fname => 'expand', args => [ > '%:p' ] ) > ->then( sub { > $self->api->vim_set_current_line( line => 'package ' . > file_to_package_name(shift) . ';' ) > })->on_done(sub{ > $msg->done; > }); > > }); > > > It's just that I am expecting the house-keeping to be done > automatically. I.e., if I do > > $foo->then(sub { ... })->then(sub{ ... }); > > it'd be neat if it would Just Work(tm) without me having to do > > my $p = $foo->then(sub { ... })->then(sub{ ... }); > > and keep `$p` around. > > > But you stirred stuff with `needs_all`. I think I have a plan B that > will work. Thanks again! :-)
Show quoted text
> Since I think the current behaviour is by design, this can probably be > closed.
Agreed. For me it's a show stopper, but I was able to migrate to Stevan Little's Promises, which has a different implementation. Thanks!