Class: Concurrent::Map
- Inherits:
-
Collection::MapImplementation
- Object
- Concurrent::Map
- Defined in:
- lib/concurrent/map.rb
Overview
‘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 = Concurrent::Map.new
Instance Method Summary collapse
- #[](key) ⇒ Object (also: #get)
-
#compute ⇒ Object
This method is atomic.
-
#compute_if_absent ⇒ Object
This method is atomic.
-
#compute_if_present ⇒ Object
This method is atomic.
-
#delete ⇒ Object
This method is atomic.
-
#delete_pair ⇒ Object
This method is atomic.
- #each_key ⇒ Object
- #each_value ⇒ Object
- #empty? ⇒ Boolean
-
#fetch(key, default_value = NULL) ⇒ Object
The “fetch-then-act” methods of ‘Map` are not atomic.
-
#fetch_or_store(key, default_value = NULL) ⇒ Object
The “fetch-then-act” methods of ‘Map` are not atomic.
-
#get_and_set ⇒ Object
This method is atomic.
-
#initialize(options = nil, &block) ⇒ Map
constructor
A new instance of Map.
- #key(value) ⇒ Object (also: #index)
- #keys ⇒ Object
- #marshal_dump ⇒ Object
- #marshal_load(hash) ⇒ Object
-
#merge_pair ⇒ Object
This method is atomic.
-
#put_if_absent(key, value) ⇒ Object
This method is atomic.
-
#replace_if_exists ⇒ Object
This method is atomic.
-
#replace_pair ⇒ Object
This method is atomic.
- #size ⇒ Object
- #value?(value) ⇒ Boolean
- #values ⇒ Object
Constructor Details
#initialize(options = nil, &block) ⇒ Map
Returns a new instance of Map.
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/concurrent/map.rb', line 81 def initialize( = nil, &block) if .kind_of?(::Hash) () else = nil end super() @default_proc = block end |
Instance Method Details
#[](key) ⇒ Object Also known as: get
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# 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 |
#compute ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 60
|
#compute_if_absent ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 54
|
#compute_if_present ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 57
|
#delete ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 75
|
#delete_pair ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/concurrent/map.rb', line 81 def initialize( = nil, &block) if .kind_of?(::Hash) () else = nil end super() @default_proc = block end |
#each_key ⇒ Object
166 167 168 |
# File 'lib/concurrent/map.rb', line 166 def each_key each_pair {|k, v| yield k} end |
#each_value ⇒ Object
170 171 172 |
# File 'lib/concurrent/map.rb', line 170 def each_value each_pair {|k, v| yield v} end |
#empty? ⇒ Boolean
180 181 182 183 |
# File 'lib/concurrent/map.rb', line 180 def empty? each_pair {|k, v| return false} true end |
#fetch(key, default_value = NULL) ⇒ Object
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.
118 119 120 121 122 123 124 125 126 127 128 |
# 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 |
#fetch_or_store(key, default_value = NULL) ⇒ Object
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.
131 132 133 134 135 |
# 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 |
#get_and_set ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 72
|
#key(value) ⇒ Object Also known as: index
174 175 176 177 |
# File 'lib/concurrent/map.rb', line 174 def key(value) each_pair {|k, v| return k if v == value} nil end |
#keys ⇒ Object
154 155 156 157 158 |
# File 'lib/concurrent/map.rb', line 154 def keys arr = [] each_pair {|k, v| arr << k} arr end |
#marshal_dump ⇒ Object
191 192 193 194 195 196 |
# File 'lib/concurrent/map.rb', line 191 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 |
#marshal_load(hash) ⇒ Object
198 199 200 201 |
# File 'lib/concurrent/map.rb', line 198 def marshal_load(hash) initialize populate_from(hash) end |
#merge_pair ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 63
|
#put_if_absent(key, value) ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 51
|
#replace_if_exists ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 69
|
#replace_pair ⇒ Object
This method is atomic. Atomic methods of ‘Map` which accept a block do not allow the `self` instance to be used within the block. Doing so will cause a deadlock.
|
# File 'lib/concurrent/map.rb', line 66
|
#size ⇒ Object
185 186 187 188 189 |
# File 'lib/concurrent/map.rb', line 185 def size count = 0 each_pair {|k, v| count += 1} count end |
#value?(value) ⇒ Boolean
147 148 149 150 151 152 |
# File 'lib/concurrent/map.rb', line 147 def value?(value) each_value do |v| return true if value.equal?(v) end false end |
#values ⇒ Object
160 161 162 163 164 |
# File 'lib/concurrent/map.rb', line 160 def values arr = [] each_pair {|k, v| arr << v} arr end |