Skip to content

Instantly share code, notes, and snippets.

@jaynetics
Created January 15, 2023 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaynetics/8a1d35bd470312a620c4d44e0047330a to your computer and use it in GitHub Desktop.
Save jaynetics/8a1d35bd470312a620c4d44e0047330a to your computer and use it in GitHub Desktop.
A self-cleaning weak-ref registry to retrieve object instances by their object_id in Ruby
# This allows doing
#
# Foo.prepend(WeakRefRegistry)
#
# foo = Foo.new # => #<Foo:0x1>
# foo_id = foo.object_id # => 1234
# Foo.registry.fetch(foo_id) # => #<Foo:0x1>
#
# I.e. retrieve Foo instances by their object_id,
# without affecting garbage collection.
#
# This is basically a slighty faster alternative to doing
# `ObjectSpace.each_object(Foo).find { |f| f.object_id == foo_id }`
require 'weakref'
module WeakRefRegistry
def initialize(...)
super
self.class.registry.store(object_id, WeakRef.new(self))
ObjectSpace.define_finalizer(self, self.class.finalizer)
end
def self.included(*) = raise("#{self} must be prepended")
def self.prepended(klass)
def klass.registry = @registry ||= Registry.new
def klass.finalizer = ->(object_id){ registry.delete(object_id) }
end
class Registry
def fetch(...) = data.fetch(...)
def store(...) = data.store(...)
def delete(...) = data.delete(...)
private
def data
@data ||= {}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment