This repository has been archived by the owner on Jan 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 41
Explainer: Clarify when the finalization callback is called #148
Open
mhofman
wants to merge
1
commit into
tc39:master
Choose a base branch
from
mhofman:explainer-clarify-finalizer-calls
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,7 +80,9 @@ All that said, sometimes finalizers are the right answer to a problem. The foll | |
|
||
Finalizers can locate external resource leaks. For example, if an open file is garbage collected, the underlying operating system resource could be leaked. Although the OS will likely free the resources when the process exits, this sort of leak could make long-running processes eventually exhaust the number of file handles available. To catch these bugs, a `FinalizationGroup` can be used to log the existence of file objects which are garbage collected before being closed. | ||
|
||
The `FinalizationGroup` class represents a group of objects registered with a common finalizer callback. This construct can be used to inform the developer about the never-closed files. | ||
The `FinalizationGroup` class represents a group of objects sharing common finalization logic. | ||
A finalizer callback is invoked after any of the objects registered with the group have been garbage collected. | ||
This construct can be used to inform the developer about the never-closed files. | ||
|
||
```js | ||
class FileStream { | ||
|
@@ -126,7 +128,8 @@ This example shows usage of the whole `FinalizationGroup` API: | |
- The object whose lifetime we're concerned with. Here, that's `this`, the `FileStream` object. | ||
- A “holdings” value, which is used to represent that object when cleaning it up in the finalizer. Here, the holdings are the underlying `File` object. | ||
- An unregistration token, which is passed to the `unregister` method when the finalizer is no longer needed. Here we use `this`, the `FileStream` object itself, since `FinalizationGroup` doesn't hold a strong reference to the unregister token. | ||
- The `FinalizationGroup` constructor is called with a callback as an argument. This callback is called with an iterator of the holdings values. | ||
- The `FinalizationGroup` constructor is called with a callback as an argument. This callback is called after a garbage collection occurred and at least one registered object was collected. The finalizer callback is called with an iterator of the holdings values for the registered objects that were collected.\ | ||
In this case a single FinalizationGroup is shared by all `File` objects as a static field of the `File` class. The class' `#cleanUp` callback will be invoked when any `File` instance was garbage collected. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. - In this case a single FinalizationGroup is shared by all `File` objects as a static field of the `File` class. The class' `#cleanUp` callback will be invoked when any `File` instance was garbage collected.
+ In this case a single FinalizationGroup is shared by all `File` objects as a static field of the `File` class. The class' `#cleanUp` callback may be invoked when any `File` instance was garbage collected. |
||
|
||
The finalizer callback is called *after* the object is garbage collected, a pattern which is sometimes called "post-mortem". For this reason, a separate "holdings" value is put in the iterator, rather than the original object--the object's already gone, so it can't be used. | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the
\
at the end intentional?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the part were it says the
callback may be called after a gc
reflects the current normative text as we can't assert if the callback will be called. This reflects an important aspect of the feature as a consecutive GC can't trigger the callback anymore if the object was collected before, in any previous GC.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a collecting engine, if an object registered with the FinalizationGroup is collected, the callback will be called, except if
cleanupSome
is called between collection and scheduled callback invocation, and the iterator is consumed (or if process is terminated, of course).I don't think consecutive GC changes this. The callback will be invoked once.
Now we can probably clarify that the callback is invoked only if an object is newly collected, not for previously collected objects which holdings were not consumed. I don't think "may be called" clarifies that enough. Maybe replacing
was collected
byhas just been collected
would help?We could probably clarify the interaction of iterators and collection executions, adding something like this to the following paragraph:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for what the spec says, callback may be called or not.
consecutive GC can't make the callback be called for the previously collected references. So it's the 1 chance opportunity.
once or zero times. Per spec text.
Yes, with the nit of "callback may be invoked".
sure.
The example looks good, the only nit picking part is:
that is actually:
The only goal I have is to reflect the spec text, even if a specific implementation will secure it being called. It remains optional.