lib/logstash-docket/util/threadsafe_index.rb (32 lines of code) (raw):

# encoding: utf-8 require 'thread' # Mutex module LogstashDocket module Util ## # A {@link ThreadsafeIndex} provides threadsafe get-or-set semantics using # the generator with which it was instantiated. class ThreadsafeIndex ## # @yieldparam key [Object]: the object for which to generate a value # @yieldreturn [Object]: the value henceforth to be used for the given key def initialize(&generator) @index = Hash.new @mutex = Mutex.new @generator = generator end ## # Fetches the value for the given key, potentially creating it using # the generator block provided at instantiation. # # @param key [Object]: the key object # @return [Object] def fetch(key) # attempt to fetch the value without acquiring a lock @index.fetch(key) do @mutex.synchronize do # return the value if it was set before we could # acquire the lock return @index.fetch(key) if @index.include?(key) @index.store(key, @generator.call(key)) end end end ## # Iterate over the objects currently stored in the index without # generating more. # # @yieldparam key [Object] # @yieldparam value [Object] # @yieldreturn [void] def each return enum_for(:each) unless block_given? @mutex.synchronize { @index.to_a }.each do |key, value| yield key, value end end def each_value each.map(&:last) end def clear @mutex.synchronize { @index.clear } end end end end