mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 04:07:58 +00:00
[DOC] Improve docs for ObjectSpace.define_finalizer
This commit is contained in:
parent
7e0e9984d0
commit
19450d85d6
Notes:
git
2026-01-18 15:47:39 +00:00
87
gc.c
87
gc.c
@ -1709,63 +1709,68 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ObjectSpace.define_finalizer(obj, aProc=proc())
|
||||
* ObjectSpace.define_finalizer(obj) {|id| ... } -> array
|
||||
* ObjectSpace.define_finalizer(obj, finalizer) -> array
|
||||
*
|
||||
* Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
|
||||
* was destroyed. The object ID of the <i>obj</i> will be passed
|
||||
* as an argument to <i>aProc</i>. If <i>aProc</i> is a lambda or
|
||||
* method, make sure it can be called with a single argument.
|
||||
* Adds a new finalizer for +obj+ that is called when +obj+ is destroyed
|
||||
* by the garbage collector or when Ruby shuts down (which ever comes first).
|
||||
*
|
||||
* The return value is an array <code>[0, aProc]</code>.
|
||||
* With a block given, uses the block as the callback. Without a block given,
|
||||
* uses a callable object +finalizer+ as the callback. The callback is called
|
||||
* when +obj+ is destroyed with a single argument +id+ which is the object
|
||||
* ID of +obj+ (see Object#object_id).
|
||||
*
|
||||
* 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.
|
||||
* The return value is an array <code>[0, callback]</code>, where +callback+
|
||||
* is a Proc created from the block if one was given or +finalizer+ otherwise.
|
||||
*
|
||||
* Note that defining a finalizer in an instance method of the object may prevent
|
||||
* the object from being garbage collected since if the block or +finalizer+ refers
|
||||
* to +obj+ then +obj+ will never be reclaimed by the garbage collector. For example,
|
||||
* the following script demonstrates the issue:
|
||||
*
|
||||
* 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}"
|
||||
* }
|
||||
* def define_final
|
||||
* ObjectSpace.define_finalizer(self) do |id|
|
||||
* puts "Running finalizer for #{id}!"
|
||||
* end
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* class Bar
|
||||
* class Remover
|
||||
* def initialize(data_needed_for_finalization)
|
||||
* @data_needed_for_finalization = data_needed_for_finalization
|
||||
* end
|
||||
* obj = Foo.new
|
||||
* obj.define_final
|
||||
*
|
||||
* There are two patterns to solve this issue:
|
||||
*
|
||||
* - Create the finalizer in a non-instance method so it can safely capture
|
||||
* the needed state:
|
||||
*
|
||||
* class Foo
|
||||
* def define_final
|
||||
* ObjectSpace.define_finalizer(self, self.class.create_finalizer)
|
||||
* end
|
||||
*
|
||||
* def self.create_finalizer
|
||||
* proc do |id|
|
||||
* puts "Running finalizer for #{id}!"
|
||||
* end
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* - Use a callable object:
|
||||
*
|
||||
* class Foo
|
||||
* class Finalizer
|
||||
* def call(id)
|
||||
* puts "finalizing #{@data_needed_for_finalization}"
|
||||
* puts "Running finalizer for #{id}!"
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* def initialize(data_needed_for_finalization)
|
||||
* ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
|
||||
* def define_final
|
||||
* ObjectSpace.define_finalizer(self, Finalizer.new)
|
||||
* 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
|
||||
* Note that finalization can be unpredictable and is never guaranteed
|
||||
* to be run except on exit.
|
||||
*/
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user