Skip to content

Commit 19450d8

Browse files
committed
[DOC] Improve docs for ObjectSpace.define_finalizer
1 parent 7e0e998 commit 19450d8

File tree

1 file changed

+44
-39
lines changed

1 file changed

+44
-39
lines changed

gc.c

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,63 +1709,68 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
17091709

17101710
/*
17111711
* call-seq:
1712-
* ObjectSpace.define_finalizer(obj, aProc=proc())
1712+
* ObjectSpace.define_finalizer(obj) {|id| ... } -> array
1713+
* ObjectSpace.define_finalizer(obj, finalizer) -> array
17131714
*
1714-
* Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
1715-
* was destroyed. The object ID of the <i>obj</i> will be passed
1716-
* as an argument to <i>aProc</i>. If <i>aProc</i> is a lambda or
1717-
* method, make sure it can be called with a single argument.
1715+
* Adds a new finalizer for +obj+ that is called when +obj+ is destroyed
1716+
* by the garbage collector or when Ruby shuts down (which ever comes first).
17181717
*
1719-
* The return value is an array <code>[0, aProc]</code>.
1718+
* With a block given, uses the block as the callback. Without a block given,
1719+
* uses a callable object +finalizer+ as the callback. The callback is called
1720+
* when +obj+ is destroyed with a single argument +id+ which is the object
1721+
* ID of +obj+ (see Object#object_id).
17201722
*
1721-
* The two recommended patterns are to either create the finaliser proc
1722-
* in a non-instance method where it can safely capture the needed state,
1723-
* or to use a custom callable object that stores the needed state
1724-
* explicitly as instance variables.
1723+
* The return value is an array <code>[0, callback]</code>, where +callback+
1724+
* is a Proc created from the block if one was given or +finalizer+ otherwise.
17251725
*
1726-
* class Foo
1727-
* def initialize(data_needed_for_finalization)
1728-
* ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization))
1729-
* end
1726+
* Note that defining a finalizer in an instance method of the object may prevent
1727+
* the object from being garbage collected since if the block or +finalizer+ refers
1728+
* to +obj+ then +obj+ will never be reclaimed by the garbage collector. For example,
1729+
* the following script demonstrates the issue:
17301730
*
1731-
* def self.create_finalizer(data_needed_for_finalization)
1732-
* proc {
1733-
* puts "finalizing #{data_needed_for_finalization}"
1734-
* }
1731+
* class Foo
1732+
* def define_final
1733+
* ObjectSpace.define_finalizer(self) do |id|
1734+
* puts "Running finalizer for #{id}!"
1735+
* end
17351736
* end
17361737
* end
17371738
*
1738-
* class Bar
1739-
* class Remover
1740-
* def initialize(data_needed_for_finalization)
1741-
* @data_needed_for_finalization = data_needed_for_finalization
1742-
* end
1739+
* obj = Foo.new
1740+
* obj.define_final
17431741
*
1744-
* def call(id)
1745-
* puts "finalizing #{@data_needed_for_finalization}"
1746-
* end
1742+
* There are two patterns to solve this issue:
1743+
*
1744+
* - Create the finalizer in a non-instance method so it can safely capture
1745+
* the needed state:
1746+
*
1747+
* class Foo
1748+
* def define_final
1749+
* ObjectSpace.define_finalizer(self, self.class.create_finalizer)
17471750
* end
17481751
*
1749-
* def initialize(data_needed_for_finalization)
1750-
* ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
1752+
* def self.create_finalizer
1753+
* proc do |id|
1754+
* puts "Running finalizer for #{id}!"
1755+
* end
17511756
* end
17521757
* end
17531758
*
1754-
* Note that if your finalizer references the object to be
1755-
* finalized it will never be run on GC, although it will still be
1756-
* run at exit. You will get a warning if you capture the object
1757-
* to be finalized as the receiver of the finalizer.
1759+
* - Use a callable object:
1760+
*
1761+
* class Foo
1762+
* class Finalizer
1763+
* def call(id)
1764+
* puts "Running finalizer for #{id}!"
1765+
* end
1766+
* end
17581767
*
1759-
* class CapturesSelf
1760-
* def initialize(name)
1761-
* ObjectSpace.define_finalizer(self, proc {
1762-
* # this finalizer will only be run on exit
1763-
* puts "finalizing #{name}"
1764-
* })
1768+
* def define_final
1769+
* ObjectSpace.define_finalizer(self, Finalizer.new)
17651770
* end
17661771
* end
17671772
*
1768-
* Also note that finalization can be unpredictable and is never guaranteed
1773+
* Note that finalization can be unpredictable and is never guaranteed
17691774
* to be run except on exit.
17701775
*/
17711776

0 commit comments

Comments
 (0)