Skip to content

Commit

Permalink
Move supply/react impl classes out of sub.
Browse files Browse the repository at this point in the history
The class was re-captured every call. This was a bit wasteful. More
notably, however, it led to the class block being lexically captured
by something with a caller chain that eventually led back to the outer
before, meaning that supply blocks might end up building a reference
chain consisting of all the frames involved in processing all of the
prior messages! This could leak a huge amount of memory.
  • Loading branch information
jnthn committed Aug 11, 2017
1 parent ed87f99 commit 5fcce67
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions src/core/Supply.pm
Expand Up @@ -1651,8 +1651,8 @@ my class Supplier::Preserving is Supplier {
}
}

sub SUPPLY(&block) {
my class SupplyBlockState {
augment class Rakudo::Internals {
class SupplyBlockState {
has &.emit;
has &.done;
has &.quit;
Expand All @@ -1679,11 +1679,15 @@ sub SUPPLY(&block) {
}

method add-active-tap($tap --> Nil) {
$!lock.protect: { %!active-taps{nqp::objectid($tap)} = $tap }
$!lock.protect: {
%!active-taps{nqp::objectid($tap)} = $tap;
}
}

method delete-active-tap($tap --> Nil) {
$!lock.protect: { %!active-taps{nqp::objectid($tap)}:delete }
$!lock.protect: {
%!active-taps{nqp::objectid($tap)}:delete;
}
}

method consume-active-taps() {
Expand Down Expand Up @@ -1720,13 +1724,13 @@ sub SUPPLY(&block) {
}
}

Supply.new(class :: does Tappable {
class SupplyBlockTappable does Tappable {
has &!block;

submethod BUILD(:&!block --> Nil) { }

method tap(&emit, &done, &quit) {
my $state = SupplyBlockState.new(:&emit, :&done, :&quit);
my $state = Rakudo::Internals::SupplyBlockState.new(:&emit, :&done, :&quit);
self!run-supply-code(&!block, $state);
if nqp::istype(&!block,Block) {
$state.close-phasers.push(.clone) for &!block.phasers('CLOSE')
Expand Down Expand Up @@ -1818,7 +1822,11 @@ sub SUPPLY(&block) {
method live(--> False) { }
method sane(--> True) { }
method serial(--> True) { }
}.new(:&block))
}
}

sub SUPPLY(&block) {
Supply.new(Rakudo::Internals::SupplyBlockTappable.new(:&block))
}

sub WHENEVER(Supply() $supply, &block) {
Expand Down

0 comments on commit 5fcce67

Please sign in to comment.