class Puppet::Pops::Types::RecursionGuard
Keeps track of self recursion of conceptual 'this' and 'that' instances using two separate maps and a state. The class is used when tracking self recursion in two objects ('this' and 'that') simultaneously. A typical example of when this is needed is when testing if 'that' Puppet
Type
is assignable to 'this' Puppet
Type
since both types may contain self references.
All comparisons are made using the `object_id` of the instance rather than the instance itself.
@api private
Constants
- NO_SELF_RECURSION
- SELF_RECURSION_IN_BOTH
- SELF_RECURSION_IN_THAT
- SELF_RECURSION_IN_THIS
Attributes
Public Class Methods
# File lib/puppet/pops/types/recursion_guard.rb 19 def initialize 20 @state = NO_SELF_RECURSION 21 end
Public Instance Methods
Add the given argument as 'that' and return the resulting state @param instance [Object] the instance to add @return [Integer] the resulting state
# File lib/puppet/pops/types/recursion_guard.rb 90 def add_that(instance) 91 if (@state & SELF_RECURSION_IN_THAT) == 0 92 @state = @state | SELF_RECURSION_IN_THAT if that_put(instance) 93 end 94 @state 95 end
Add the given argument as 'this' and return the resulting state @param instance [Object] the instance to add @return [Integer] the resulting state
# File lib/puppet/pops/types/recursion_guard.rb 80 def add_this(instance) 81 if (@state & SELF_RECURSION_IN_THIS) == 0 82 @state = @state | SELF_RECURSION_IN_THIS if this_put(instance) 83 end 84 @state 85 end
Checks if recursion was detected for the given argument in the 'that' context @param instance [Object] the instance to check @return [Integer] the resulting state
# File lib/puppet/pops/types/recursion_guard.rb 33 def recursive_that?(instance) 34 instance_variable_defined?(:@recursive_that_map) && @recursive_that_map.has_key?(instance.object_id) 35 end
Checks if recursion was detected for the given argument in the 'this' context @param instance [Object] the instance to check @return [Integer] the resulting state
# File lib/puppet/pops/types/recursion_guard.rb 26 def recursive_this?(instance) 27 instance_variable_defined?(:@recursive_this_map) && @recursive_this_map.has_key?(instance.object_id) 28 end
@return the number of objects added to the `that` map
# File lib/puppet/pops/types/recursion_guard.rb 103 def that_count 104 instance_variable_defined?(:@that_map) ? @that_map.size : 0 105 end
@return the number of objects added to the `this` map
# File lib/puppet/pops/types/recursion_guard.rb 98 def this_count 99 instance_variable_defined?(:@this_map) ? @this_map.size : 0 100 end
Add the given argument as 'that' invoke the given block with the resulting state @param instance [Object] the instance to add @return [Object] the result of yielding
# File lib/puppet/pops/types/recursion_guard.rb 60 def with_that(instance) 61 if (@state & SELF_RECURSION_IN_THAT) == 0 62 tc = that_count 63 @state = @state | SELF_RECURSION_IN_THAT if that_put(instance) 64 if tc < that_count 65 # recursive state detected 66 result = yield(@state) 67 68 # pop state 69 @state &= ~SELF_RECURSION_IN_THAT 70 @that_map.delete(instance.object_id) 71 return result 72 end 73 end 74 yield(@state) 75 end
Add the given argument as 'this' invoke the given block with the resulting state @param instance [Object] the instance to add @return [Object] the result of yielding
# File lib/puppet/pops/types/recursion_guard.rb 40 def with_this(instance) 41 if (@state & SELF_RECURSION_IN_THIS) == 0 42 tc = this_count 43 @state = @state | SELF_RECURSION_IN_THIS if this_put(instance) 44 if tc < this_count 45 # recursive state detected 46 result = yield(@state) 47 48 # pop state 49 @state &= ~SELF_RECURSION_IN_THIS 50 @this_map.delete(instance.object_id) 51 return result 52 end 53 end 54 yield(@state) 55 end
Private Instance Methods
# File lib/puppet/pops/types/recursion_guard.rb 122 def that_put(o) 123 id = o.object_id 124 @that_map ||= {} 125 if @that_map.has_key?(id) 126 @recursive_that_map ||= {} 127 @recursive_that_map[id] = true 128 true 129 else 130 @that_map[id] = true 131 false 132 end 133 end
# File lib/puppet/pops/types/recursion_guard.rb 109 def this_put(o) 110 id = o.object_id 111 @this_map ||= {} 112 if @this_map.has_key?(id) 113 @recursive_this_map ||= {} 114 @recursive_this_map[id] = true 115 true 116 else 117 @this_map[id] = true 118 false 119 end 120 end