Skip to content

Commit 90cc27e

Browse files
committed
Prevent SystemStackError when calculating slot shares
Avoids infinitely recursing through sibling slots when all demands are zero. Ref #58 Ref #59
1 parent 9272d50 commit 90cc27e

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

lib/refinery/slot.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ def edges
6868
#
6969
# * Otherwise, the share cannot be determined automatically.
7070
#
71+
# recursing - Flag indicating if `share` is being called from the `share`
72+
# method of other slot. Prevents infinitely recursing through
73+
# all the slots of a node when demand is zero and the shares
74+
# cannot be calculated.
75+
#
7176
# Returns a Rational or nil.
72-
def share
77+
def share(recursing = false)
7378
if (explicit = get(:share)) then return explicit end
7479

7580
slots = @node.slots.public_send(@direction)
@@ -91,7 +96,8 @@ def share
9196
# Special-case for when a node demand is zero, and contains a slot
9297
# with "normal" links, and a slot with overflow links.
9398
set(:share, 0.0)
94-
elsif node_demand.zero? && others.all?(&:share)
99+
elsif ! recursing && node_demand.zero? &&
100+
others.all? { |o| o.share(true) }
95101
# Opposite of the special case above.
96102
set(:share, 1.0 - others.sum(&:share))
97103
elsif ! node_demand.zero?

spec/integration/parent_and_two_children_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,26 @@
267267
mother.slots.out(:electricity).set(:share, 0.4)
268268
end
269269

270+
context 'and the children have zero demand' do
271+
# [M]
272+
# :gas / \ :electricity
273+
# (0) [C] [S] (0)
274+
before do
275+
mother.slots.out(:gas).set(:share, nil)
276+
mother.slots.out(:electricity).set(:share, nil)
277+
278+
child.set(:demand, 0.0)
279+
sibling.set(:demand, 0.0)
280+
281+
calculate!
282+
end
283+
284+
it 'does not set the slot shares' do
285+
expect(mother.slots.out(:gas).share).to be_nil
286+
expect(mother.slots.out(:electricity).share).to be_nil
287+
end
288+
end
289+
270290
context 'and the parent defines demand' do
271291
# [M] (50)
272292
# :gas / \ :electricity

0 commit comments

Comments
 (0)