Method: ObjectSpace#define_finalizer
- Defined in:
- gc.c
#define_finalizer(obj, aProc = proc()) ⇒ Object (private)
Adds aProc as a finalizer, to be called after obj was destroyed. The object ID of the obj will be passed as an argument to aProc. If aProc is a lambda or method, make sure it can be called with a single argument.
The return value is an array [0, aProc].
The two recommended patterns are to either create the finaliser proc in a non-instance method where it can safely capture the needed state, or to use a custom callable object that stores the needed state explicitly as instance variables.
class Foo
def initialize(data_needed_for_finalization)
ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization))
end
def self.create_finalizer(data_needed_for_finalization)
proc {
puts "finalizing #{data_needed_for_finalization}"
}
end
end
class Bar
class Remover
def initialize(data_needed_for_finalization)
@data_needed_for_finalization = data_needed_for_finalization
end
def call(id)
puts "finalizing #{@data_needed_for_finalization}"
end
end
def initialize(data_needed_for_finalization)
ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
end
end
Note that if your finalizer references the object to be finalized it will never be run on GC, although it will still be run at exit. You will get a warning if you capture the object to be finalized as the receiver of the finalizer.
class CapturesSelf
def initialize(name)
ObjectSpace.define_finalizer(self, proc {
# this finalizer will only be run on exit
puts "finalizing #{name}"
})
end
end
Also note that finalization can be unpredictable and is never guaranteed to be run except on exit.
3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 |
# File 'gc.c', line 3540 static VALUE define_final(int argc, VALUE *argv, VALUE os) { VALUE obj, block; rb_scan_args(argc, argv, "11", &obj, &block); should_be_finalizable(obj); if (argc == 1) { block = rb_block_proc(); } else { should_be_callable(block); } if (rb_callable_receiver(block) == obj) { rb_warn("finalizer references object to be finalized"); } return define_final0(obj, block); } |