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 20 def initialize 21 @state = NO_SELF_RECURSION 22 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 91 def add_that(instance) 92 if (@state & SELF_RECURSION_IN_THAT) == 0 93 @state = @state | SELF_RECURSION_IN_THAT if that_put(instance) 94 end 95 @state 96 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 81 def add_this(instance) 82 if (@state & SELF_RECURSION_IN_THIS) == 0 83 @state = @state | SELF_RECURSION_IN_THIS if this_put(instance) 84 end 85 @state 86 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 34 def recursive_that?(instance) 35 instance_variable_defined?(:@recursive_that_map) && @recursive_that_map.has_key?(instance.object_id) 36 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 27 def recursive_this?(instance) 28 instance_variable_defined?(:@recursive_this_map) && @recursive_this_map.has_key?(instance.object_id) 29 end
@return the number of objects added to the `that` map
# File lib/puppet/pops/types/recursion_guard.rb 104 def that_count 105 instance_variable_defined?(:@that_map) ? @that_map.size : 0 106 end
@return the number of objects added to the `this` map
# File lib/puppet/pops/types/recursion_guard.rb 99 def this_count 100 instance_variable_defined?(:@this_map) ? @this_map.size : 0 101 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 61 def with_that(instance) 62 if (@state & SELF_RECURSION_IN_THAT) == 0 63 tc = that_count 64 @state = @state | SELF_RECURSION_IN_THAT if that_put(instance) 65 if tc < that_count 66 # recursive state detected 67 result = yield(@state) 68 69 # pop state 70 @state &= ~SELF_RECURSION_IN_THAT 71 @that_map.delete(instance.object_id) 72 return result 73 end 74 end 75 yield(@state) 76 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 41 def with_this(instance) 42 if (@state & SELF_RECURSION_IN_THIS) == 0 43 tc = this_count 44 @state = @state | SELF_RECURSION_IN_THIS if this_put(instance) 45 if tc < this_count 46 # recursive state detected 47 result = yield(@state) 48 49 # pop state 50 @state &= ~SELF_RECURSION_IN_THIS 51 @this_map.delete(instance.object_id) 52 return result 53 end 54 end 55 yield(@state) 56 end
Private Instance Methods
# File lib/puppet/pops/types/recursion_guard.rb 123 def that_put(o) 124 id = o.object_id 125 @that_map ||= {} 126 if @that_map.has_key?(id) 127 @recursive_that_map ||= {} 128 @recursive_that_map[id] = true 129 true 130 else 131 @that_map[id] = true 132 false 133 end 134 end
# File lib/puppet/pops/types/recursion_guard.rb 110 def this_put(o) 111 id = o.object_id 112 @this_map ||= {} 113 if @this_map.has_key?(id) 114 @recursive_this_map ||= {} 115 @recursive_this_map[id] = true 116 true 117 else 118 @this_map[id] = true 119 false 120 end 121 end