develooper Front page | perl.perl6.users | Postings from January 2021

Nested `whenever` (was Re: Help with bug)

Thread Previous | Thread Next
From:
Gianni Ceccarelli
Date:
January 5, 2021 12:25
Subject:
Nested `whenever` (was Re: Help with bug)
Message ID:
20210105122513.63c4e2a6@nautilus
On 2020-12-30 Gianni Ceccarelli <dakkar@thenautilus.net> wrote:
> Also, my understanding of ``whenever`` is that it's adding a hook into
> the event loop, and only leaving the surrounding ``react`` (or
> ``supply``) will remove that hook (people who understand this better
> than I do: please correct me!). If that's true, adding a hook many
> times on the same condition looks wrong to me…

My understanding seems to be mostly correct::

  use v6.d;

  my Channel $outer .=new;
  my Supplier $inner .=new;
  my $inner-s = $inner.Supply;
  my Promise $done-with-outer .=new;

  my $receiver = start {
      react {
          whenever $outer -> $outer-value {
              say "received outer $outer-value";
              whenever $inner-s -> $inner-value {
                  say "received inner $inner-value for outer $outer-value";
                  done if $inner-value >= 3 && $outer-value >= 3;
              }
              $done-with-outer.keep() if $outer-value >= 3;
          }
      }
  }

  $outer.send($_) for ^4;
  await $done-with-outer;
  $inner.emit($_) for ^4;
  await $receiver;

prints::

  received outer 0
  received outer 1
  received outer 2
  received outer 3
  received inner 0 for outer 0
  received inner 0 for outer 1
  received inner 0 for outer 2
  received inner 0 for outer 3
  received inner 1 for outer 0
  received inner 1 for outer 1
  received inner 1 for outer 2
  received inner 1 for outer 3
  received inner 2 for outer 0
  received inner 2 for outer 1
  received inner 2 for outer 2
  received inner 2 for outer 3
  received inner 3 for outer 0
  received inner 3 for outer 1
  received inner 3 for outer 2
  received inner 3 for outer 3

so the inner ``whenever`` really sets up a separate tap every time
it's executed.

If I change ``$inner`` to be a Channel, we only get 4 "received inner"
lines, as expected, because values in a channel are received exactly
once.

(If I change ``$outer`` to a Supplier/Supply pair… the program hangs
without printing anything, because there's a race between the main
process and the ``start``ed one, so all the ``$outer.emit`` happen
before the ``react / whenever`` can tap, and ``$done-with-outer``
never gets kept. Using ``Supplier::Preserving`` fixes that)

-- 
	Dakkar - <Mobilis in mobile>
	GPG public key fingerprint = A071 E618 DD2C 5901 9574
	                             6FE2 40EA 9883 7519 3F88
	                    key id = 0x75193F88


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About