class Concurrent::Map
`Concurrent::Map` is a hash-like object and should have much better performance characteristics, especially under high concurrency, than `Concurrent::Hash`. However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash` – for instance, it does not necessarily retain ordering by insertion time as `Hash` does. For most uses it should do fine though, and we recommend you consider `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs.
> require 'concurrent' > > map = ::new
Constants
- DEFAULT_OBJ_ID_STR_WIDTH
@!visibility private
Public Class Methods
@!method delete_pair
@!macro map_method_is_atomic
# File lib/concurrent/map.rb, line 81 def initialize(options = nil, &block) if options.kind_of?(::Hash) validate_options_hash!(options) else options = nil end super(options) @default_proc = block end
Public Instance Methods
# File lib/concurrent/map.rb, line 92 def [](key) if value = super # non-falsy value is an existing mapping, return it right away value # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value # would be returned) # note: nil == value check is not technically necessary elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL)) @default_proc.call(self, key) else value end end
# File lib/concurrent/map.rb, line 166 def each_key each_pair {|k, v| yield k} end
# File lib/concurrent/map.rb, line 174 def each_pair return enum_for :each_pair unless block_given? super end
# File lib/concurrent/map.rb, line 170 def each_value each_pair {|k, v| yield v} end
# File lib/concurrent/map.rb, line 187 def empty? each_pair {|k, v| return false} true end
@!macro [attach] map_method_not_atomic
The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended to be use as a concurrency primitive with strong happens-before guarantees. It is not intended to be used as a high-level abstraction supporting complex operations. All read and write operations are thread safe, but no guarantees are made regarding race conditions between the fetch operation and yielding to the block. Additionally, this method does not support recursion. This is due to internal constraints that are very unlikely to change in the near future.
# File lib/concurrent/map.rb, line 118 def fetch(key, default_value = NULL) if NULL != (value = get_or_default(key, NULL)) value elsif block_given? yield key elsif NULL != default_value default_value else raise_fetch_no_key end end
@!macro map_method_not_atomic
# File lib/concurrent/map.rb, line 131 def fetch_or_store(key, default_value = NULL) fetch(key) do put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value)) end end
inspect() call on its @backend i-var will bump @backend's iter level while possibly yielding GVL
# File lib/concurrent/map.rb, line 216 def inspect id_str = (object_id << 1).to_s(16).rjust(DEFAULT_OBJ_ID_STR_WIDTH, '0') "#<#{self.class.name}:0x#{id_str} entries=#{size} default_proc=#{@default_proc.inspect}>" end
# File lib/concurrent/map.rb, line 181 def key(value) each_pair {|k, v| return k if v == value} nil end
# File lib/concurrent/map.rb, line 154 def keys arr = [] each_pair {|k, v| arr << k} arr end
# File lib/concurrent/map.rb, line 198 def marshal_dump raise TypeError, "can't dump hash with default proc" if @default_proc h = {} each_pair {|k, v| h[k] = v} h end
# File lib/concurrent/map.rb, line 205 def marshal_load(hash) initialize populate_from(hash) end
@!macro map_method_is_atomic
# File lib/concurrent/map.rb, line 138 def put_if_absent(key, value) computed = false result = compute_if_absent(key) do computed = true value end computed ? nil : result end
# File lib/concurrent/map.rb, line 192 def size count = 0 each_pair {|k, v| count += 1} count end
# File lib/concurrent/map.rb, line 147 def value?(value) each_value do |v| return true if value.equal?(v) end false end
# File lib/concurrent/map.rb, line 160 def values arr = [] each_pair {|k, v| arr << v} arr end