PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
| Dir : /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/ |
| Server: Linux server1.ngambekcore.com 4.18.0-553.51.1.el8_10.x86_64 #1 SMP Wed Apr 30 04:00:07 EDT 2025 x86_64 IP: 159.198.77.92 |
| Dir : //opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/recursion_guard.rb |
module Puppet::Pops
module Types
# 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
class RecursionGuard
attr_reader :state
NO_SELF_RECURSION = 0
SELF_RECURSION_IN_THIS = 1
SELF_RECURSION_IN_THAT = 2
SELF_RECURSION_IN_BOTH = 3
def initialize
@state = NO_SELF_RECURSION
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
def recursive_this?(instance)
instance_variable_defined?(:@recursive_this_map) && @recursive_this_map.has_key?(instance.object_id)
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
def recursive_that?(instance)
instance_variable_defined?(:@recursive_that_map) && @recursive_that_map.has_key?(instance.object_id)
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
def with_this(instance)
if (@state & SELF_RECURSION_IN_THIS) == 0
tc = this_count
@state = @state | SELF_RECURSION_IN_THIS if this_put(instance)
if tc < this_count
# recursive state detected
result = yield(@state)
# pop state
@state &= ~SELF_RECURSION_IN_THIS
@this_map.delete(instance.object_id)
return result
end
end
yield(@state)
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
def with_that(instance)
if (@state & SELF_RECURSION_IN_THAT) == 0
tc = that_count
@state = @state | SELF_RECURSION_IN_THAT if that_put(instance)
if tc < that_count
# recursive state detected
result = yield(@state)
# pop state
@state &= ~SELF_RECURSION_IN_THAT
@that_map.delete(instance.object_id)
return result
end
end
yield(@state)
end
# Add the given argument as 'this' and return the resulting state
# @param instance [Object] the instance to add
# @return [Integer] the resulting state
def add_this(instance)
if (@state & SELF_RECURSION_IN_THIS) == 0
@state = @state | SELF_RECURSION_IN_THIS if this_put(instance)
end
@state
end
# Add the given argument as 'that' and return the resulting state
# @param instance [Object] the instance to add
# @return [Integer] the resulting state
def add_that(instance)
if (@state & SELF_RECURSION_IN_THAT) == 0
@state = @state | SELF_RECURSION_IN_THAT if that_put(instance)
end
@state
end
# @return the number of objects added to the `this` map
def this_count
instance_variable_defined?(:@this_map) ? @this_map.size : 0
end
# @return the number of objects added to the `that` map
def that_count
instance_variable_defined?(:@that_map) ? @that_map.size : 0
end
private
def this_put(o)
id = o.object_id
@this_map ||= {}
if @this_map.has_key?(id)
@recursive_this_map ||= {}
@recursive_this_map[id] = true
true
else
@this_map[id] = true
false
end
end
def that_put(o)
id = o.object_id
@that_map ||= {}
if @that_map.has_key?(id)
@recursive_that_map ||= {}
@recursive_that_map[id] = true
true
else
@that_map[id] = true
false
end
end
end
end
end