Class: Foobara::WeakObjectSet
- Inherits:
-
Object
- Object
- Foobara::WeakObjectSet
- Includes:
- Enumerable
- Defined in:
- foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb,
foobara-0.0.141/projects/weak_object_set/lib/foobara/weak_object_set.rb
Overview
TODO: a possible optimization: have a certain number of records before the Weakref approach kicks in that way we don’t just immediately clear out useful information without any actual memory burden
Defined Under Namespace
Classes: GarbageCleaner
Instance Attribute Summary collapse
-
#closed ⇒ Object
Returns the value of attribute closed.
- #garbage_cleaner ⇒ Object
-
#key_method ⇒ Object
Returns the value of attribute key_method.
-
#key_to_object_id ⇒ Object
Returns the value of attribute key_to_object_id.
-
#monitor ⇒ Object
Returns the value of attribute monitor.
-
#object_id_to_key ⇒ Object
Returns the value of attribute object_id_to_key.
-
#objects ⇒ Object
Returns the value of attribute objects.
Instance Method Summary collapse
- #<<(object) ⇒ Object
- #[](object_or_object_id) ⇒ Object
- #clear ⇒ Object
- #close ⇒ Object
- #closed? ⇒ Boolean
- #delete(object_or_object_id) ⇒ Object
- #each ⇒ Object
- #empty? ⇒ Boolean
- #find_by_key(key) ⇒ Object
-
#initialize(key_method = nil) ⇒ WeakObjectSet
constructor
A new instance of WeakObjectSet.
- #ref_for(object_or_object_id) ⇒ Object
- #size ⇒ Object
- #stop_garbage_cleaner ⇒ Object
Constructor Details
#initialize(key_method = nil) ⇒ WeakObjectSet
Returns a new instance of WeakObjectSet.
88 89 90 91 92 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 88 def initialize(key_method = nil) self.key_method = key_method self.monitor = Monitor.new clear end |
Instance Attribute Details
#closed ⇒ Object
Returns the value of attribute closed.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def closed @closed end |
#garbage_cleaner ⇒ Object
148 149 150 151 152 153 154 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 148 def garbage_cleaner @garbage_cleaner ||= begin queue = Queue.new GarbageCleaner.new(self, queue) end end |
#key_method ⇒ Object
Returns the value of attribute key_method.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def key_method @key_method end |
#key_to_object_id ⇒ Object
Returns the value of attribute key_to_object_id.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def key_to_object_id @key_to_object_id end |
#monitor ⇒ Object
Returns the value of attribute monitor.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def monitor @monitor end |
#object_id_to_key ⇒ Object
Returns the value of attribute object_id_to_key.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def object_id_to_key @object_id_to_key end |
#objects ⇒ Object
Returns the value of attribute objects.
85 86 87 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 85 def objects @objects end |
Instance Method Details
#<<(object) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 156 def <<(object) if closed? # :nocov: raise "Cannot add objects to a closed WeakObjectSet" # :nocov: end object_id = object.object_id monitor.synchronize do existing_object = self[object_id] if existing_object if key_method key = object.send(key_method) old_key = object_id_to_key[object_id] if key != old_key key_to_object_id.delete(old_key) if key key_to_object_id[key] = object_id object_id_to_key[object_id] = key else object_id_to_key.delete(object_id) end end end else garbage_cleaner.track(object) if key_method key = object.send(key_method) if key existing_record_object_id = key_to_object_id[key] if existing_record_object_id # Sometimes this path is hit in the test suite and sometimes not, depending on # non-deterministic behavior of the garbage collector # :nocov: delete(existing_record_object_id) # :nocov: end key_to_object_id[key] = object_id object_id_to_key[object_id] = key end end objects[object_id] = WeakRef.new(object) object end end end |
#[](object_or_object_id) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 94 def [](object_or_object_id) monitor.synchronize do ref = ref_for(object_or_object_id) object = begin ref&.__getobj__ rescue WeakRef::RefError # :nocov: nil # :nocov: end if ref&.weakref_alive? object end end end |
#clear ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 269 def clear monitor.synchronize do stop_garbage_cleaner self.objects = {} if key_method self.key_to_object_id = {} self.object_id_to_key = {} end end end |
#close ⇒ Object
249 250 251 252 253 254 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 249 def close raise if closed? self.closed = true stop_garbage_cleaner end |
#closed? ⇒ Boolean
282 283 284 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 282 def closed? closed end |
#delete(object_or_object_id) ⇒ Object
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 213 def delete(object_or_object_id) object_id = if object_or_object_id.is_a?(::Integer) object_or_object_id else object_or_object_id.object_id end monitor.synchronize do if key_method key = object_id_to_key.delete(object_id) if key key_to_object_id.delete(key) end end objects.delete(object_id) end end |
#each ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 122 def each monitor.synchronize do objects.each_value do |ref| object = begin ref.__getobj__ rescue WeakRef::RefError nil end if ref.weakref_alive? yield object end end end end |
#empty? ⇒ Boolean
142 143 144 145 146 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 142 def empty? monitor.synchronize do objects.empty? || objects.values.none?(&:weakref_alive?) end end |
#find_by_key(key) ⇒ Object
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 233 def find_by_key(key) monitor.synchronize do unless key_method # :nocov: raise "Cannot find by key if there was no key_method given." # :nocov: end object_id = key_to_object_id[key] if object_id self[object_id] end end end |
#ref_for(object_or_object_id) ⇒ Object
112 113 114 115 116 117 118 119 120 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 112 def ref_for(object_or_object_id) object_id = if object_or_object_id.is_a?(::Integer) object_or_object_id else object_or_object_id.object_id end objects[object_id] end |
#size ⇒ Object
138 139 140 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 138 def size count end |
#stop_garbage_cleaner ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'foobara-0.0.141/projects/weak_object_set/src/weak_object_set.rb', line 256 def stop_garbage_cleaner gc = nil monitor.synchronize do if @garbage_cleaner gc = garbage_cleaner self.garbage_cleaner = nil end end gc&.deactivate end |