# class Puppet::Parser::TypeLoader::Helper

Helper class that makes sure we don't try to import the same file more than once from either the same thread or different threads.

### Public Class Methods

new() click to toggle source
Calls superclass method Object.new

    # File lib/puppet/parser/type_loader.rb, line 13
    def initialize
      super
      # These hashes are indexed by filename
      @state = {} # :doing or :done
      @thread = {} # if :doing, thread that's doing the parsing
      @cond_var = {} # if :doing, condition var that will be signaled when done.
    end

### Public Instance Methods

do_once(file) { || ... } click to toggle source

Execute the supplied block exactly once per file, no matter how many threads have asked for it to run. If another thread is already executing it, wait for it to finish. If this thread is already executing it, return immediately without executing the block.

Note: the reason for returning immediately if this thread is already executing the block is to handle the case of a circular import–when this happens, we attempt to recursively re-parse a file that we are already in the process of parsing. To prevent an infinite regress we need to simply do nothing when the recursive import is attempted.

    # File lib/puppet/parser/type_loader.rb, line 33
    def do_once(file)
      need_to_execute = synchronize do
        case @state[file]
        when :doing
          if @thread[file] != Thread.current
            @cond_var[file].wait
          end
          false
        when :done
          false
        else
          @state[file] = :doing
          @thread[file] = Thread.current
          @cond_var[file] = new_cond
          true
        end
      end
      if need_to_execute
        begin
          yield
        ensure
          synchronize do
            @state[file] = :done
            @thread.delete(file)
            @cond_var.delete(file).broadcast
          end
        end
      end
    end