Skip to content

Commit

Permalink
Prevent SystemStackError when calculating slot shares
Browse files Browse the repository at this point in the history
Avoids infinitely recursing through sibling slots when all demands are
zero.

Ref #58
Ref #59
  • Loading branch information
antw committed May 8, 2018
1 parent 9272d50 commit 90cc27e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
10 changes: 8 additions & 2 deletions lib/refinery/slot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ def edges
#
# * Otherwise, the share cannot be determined automatically.
#
# recursing - Flag indicating if `share` is being called from the `share`
# method of other slot. Prevents infinitely recursing through
# all the slots of a node when demand is zero and the shares
# cannot be calculated.
#
# Returns a Rational or nil.
def share
def share(recursing = false)
if (explicit = get(:share)) then return explicit end

slots = @node.slots.public_send(@direction)
Expand All @@ -91,7 +96,8 @@ def share
# Special-case for when a node demand is zero, and contains a slot
# with "normal" links, and a slot with overflow links.
set(:share, 0.0)
elsif node_demand.zero? && others.all?(&:share)
elsif ! recursing && node_demand.zero? &&
others.all? { |o| o.share(true) }
# Opposite of the special case above.
set(:share, 1.0 - others.sum(&:share))
elsif ! node_demand.zero?
Expand Down
20 changes: 20 additions & 0 deletions spec/integration/parent_and_two_children_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,26 @@
mother.slots.out(:electricity).set(:share, 0.4)
end

context 'and the children have zero demand' do
# [M]
# :gas / \ :electricity
# (0) [C] [S] (0)
before do
mother.slots.out(:gas).set(:share, nil)
mother.slots.out(:electricity).set(:share, nil)

child.set(:demand, 0.0)
sibling.set(:demand, 0.0)

calculate!
end

it 'does not set the slot shares' do
expect(mother.slots.out(:gas).share).to be_nil
expect(mother.slots.out(:electricity).share).to be_nil
end
end

context 'and the parent defines demand' do
# [M] (50)
# :gas / \ :electricity
Expand Down

0 comments on commit 90cc27e

Please sign in to comment.