-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrfi-246.html
177 lines (130 loc) · 11.9 KB
/
srfi-246.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SRFI 246: Guardians</title>
<link href="/favicon.png" rel="icon" sizes="192x192" type="image/png">
<link rel="stylesheet" href="https://srfi.schemers.org/srfi.css" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1"></head>
<body>
<h1><a href="https://srfi.schemers.org/"><img class="srfi-logo" src="https://srfi.schemers.org/srfi-logo.svg" alt="SRFI surfboard logo" /></a>246: Guardians</h1>
<p>by R. Kent Dybvig (specification author) and John Cowan (shepherd)</p>
<h2 id="status">Status</h2>
<p>This SRFI is currently in <em>withdrawn</em> status. Here is <a href="https://srfi.schemers.org/srfi-process.html">an explanation</a> of each status that a SRFI can hold. To provide input on this SRFI, please send email to <code><a href="mailto:srfi+minus+246+at+srfi+dotschemers+dot+org">srfi-246@<span class="antispam">nospam</span>srfi.schemers.org</a></code>. To subscribe to the list, follow <a href="https://srfi.schemers.org/srfi-list-subscribe.html">these instructions</a>. You can access previous messages via the mailing list <a href="https://srfi-email.schemers.org/srfi-246/">archive</a>.</p>
<ul>
<li>Received: 2023-09-23</li>
<li>Draft #1 published: 2023-10-12</li>
<li>Withdrawn (superseded
by <a href="https://srfi.schemers.org/srfi-254/">SRFI
254</a>): 2024-09-11
<p>editor's summary of reasons for withdrawal: This SRFI was
withdrawn by the editor because there had been no progress
since 12-2023, and because he hadn't been able to reach the
author since 5-2024. Marc Nieper-Wißkirchen has volunteered
to take over, but because he was not a co-author, a new SRFI
was forked from this one
as <a href="https://srfi.schemers.org/srfi-254/">SRFI
254</a>.</p></li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>Guardians allow programs to protect objects from deallocation by the garbage collector and to determine which objects would otherwise have been deallocated. When the object has associated non-memory resources, a program can register it with a guardian. The GC will mark inaccessible objects but will not collect them; at the program's convenience, inaccessible objects are removed from the guardian and their non-memory resources are disposed of.
Guardians allow objects to be saved from deallocation indefinitely so that they can be reused or so that clean-up or other actions can be performed using the data stored within the objects. Guardians avoid the problems associated with classical finalizers detailed in the Rationale section.</p>
<h2 id="rationale">Rationale</h2>
<p>The difficulties with classical finalizers are:</p>
<ul><li>When run directly by the garbage collector, they must be executed within a critical section, because the collector may interrupt the rest of the program at arbitrary points.</li>
<li>When cyclic and shared structures must be finalized, it may be essential to control the order in which finalization is done.</li>
<li>They do not always allow the full range of language features to be employed. For example, allocation may not be possible from within the garbage collector, as the collector may not be re-entrant. If an error is signaled while the collector is running, it is not always clear how to recover.</li>
<li>It may or may not be appropriate to examine the object being finalized in order to determine what to do with it. In particular, it may be the Right Thing to protect the object from reclamation by placing it in a variable or a container, with or without re-registering it for finalization.</li></ul>
<p>Guardians solve all of these problems at the expense of manual reclamation. Objects are preserved by a guardian; periodically, the guardian must be invoked to allow them to be reclaimed by the collector or to preserve them.</p>
<h2 id="specification">Specification</h2>
<p>Guardians are procedures that encapsulate groups of objects registered for preservation. When a guardian is created, the group of registered objects is empty. An object is registered with a guardian by passing the object as an argument to the guardian, as well as a representative object to be returned when the object is retrieved from the guardian.</p>
<p>The group of registered objects associated with a guardian is logically subdivided into two disjoint subgroups: a subgroup referred to as the <i>accessible objects group</i>, and another referred to as the <i>inaccessible objects group</i>. Inaccessible objects are objects that have been proven to be inaccessible (except through the guardian mechanism itself or through a weak reference), and accessible objects are objects that have not been proven so. Objects may be registered in more than one guardian, and a guardian may be registered in another guardian.</p>
<p>The word "proven" is important here: it may be that some objects in the accessible objects subgroup are indeed inaccessible but that this has not yet been proven. This proof may not be made in some cases until long after the object actually becomes inaccessible, typically when the collector is run.</p>
<p>Objects registered with a guardian are initially placed in the accessible objects group and are moved into the inaccessible objects group at some point after they become inaccessible. The representative of an object in the inaccessible objects group is retrieved by invoking the guardian without arguments. If there are no objects in the inaccessible objects group, the guardian returns <code>#f</code>.</p>
<p>Although an object registered without a representative and returned from a guardian has been proven otherwise inaccessible (except via a weak pointer), it has not yet been reclaimed by the storage management system and will not be reclaimed until after the last non-weak pointer to it within or outside of the guardian system has been dropped. In fact, objects that have been retrieved from a guardian have no special status in this or in any other regard. This feature circumvents the problems that might otherwise arise with shared or cyclic structure. A shared or cyclic structure consisting of inaccessible objects is preserved in its entirety, and each piece registered for preservation with any guardian is placed in the inaccessible objects set for that guardian. The programmer then has complete control over the order in which pieces of the structure are processed.</p>
<p>An object may be registered with a guardian more than once, in which case it will be retrievable more than once.</p>
<h3 id="Procedures">Procedures</h3>
<p><code>(make-guardian)</code></p>
<p>Returns a newly allocated guardian with no registered objects.</p>
<p><code>(guardian?</code> <em>obj</em><code>)</code></p>
<p>Returns <code>#t</code> if obj is a guardian and <code>#f</code> otherwise.</p>
<p><code>(</code><em>guardian obj</em> [ <em>rep</em> ]<code>)</code></p>
<p>Registers <em>obj</em> with <em>guardian</em>, specifying <em>rep</em> as the representative object. If <em>rep</em> is omitted, the representative object is <em>obj</em>.</p>
<p><code>(</code><em>guardian</em><code>)</code></p>
<p>Returns the representative of a single object from <em>guardian</em> and removes the object.</p>
<p><code>(unregister-guardian </code><em>guardian</em><code>)</code></p>
<p>Unregisters all the accessible objects currently registered with <em>guardian</em>, with one caveat. Objects registered by other threads than the current thread are not necessarily removed from <em>guardian</em>. To ensure that all objects are unregistered in a multithreaded application, a single thread can be used both to register and unregister objects. Alternatively, an application can arrange to define a handler that calls <code>unregister-guardian</code> after it calls the collector.</p>
<p>In any case, <code>unregister-guardian</code> returns a list containing the representative objects corresponding to the objects that it unregisters, with duplicates as appropriate if the same object is registered more than once with <em>guardian</em>. Objects already resurrected but not yet retrieved from <em>guardian</em> are not included in the list but remain retrievable from <em>guardian</em>.</p>
<h2 id="abstract-example">Abstract Example</h2>
<p>This example shows how to manage manually allocated and deallocated
resources automatically by wrapping them in a <code>handle</code> record
type, which can also contain auxiliary data. For example, a resource
might be a POSIX file descriptor and a handle might be a port.</p>
<p>This implementation is not thread-safe.</p>
<pre><code>(library (resources)
(export
make-handle handle? get-handle-resource
get-handle-auxdata set-handle-auxdata!)
(import
(scheme base)
(scheme guardians))
(begin
;;; Allocate resources using handles.
;; Allocate and deallocate a resource which is not managed by Scheme.
(define (allocate-resource) ...)
(define (free-resource resource) ...)
;; Handle type. Auxdata is Scheme data associated with the resource.
(define-record-type handle
(raw-make-handle resource auxdata)
handle?
(auxdata get-handle-auxdata set-handle-auxdata!)
(resource get-resource))
;; The global guardian for all handles
(define handle-guardian (make-guardian))
;; Return an initialized handle.
(define (make-handle auxdata)
(let* ((resource (allocate-resource))
(handle (raw-make-handle resource auxdata)))
;; Free up resources whose handles are garbage.
;; Alternative: (for-each free-resource
;; (unregister-guardian handle-guardian))
(let loop ((r (handle-guardian)))
(when r
(free-resource r)
(loop (handle-guardian)))
;; Protect new resource and return handle.
;; The resource is the representative object.
(handle-guardian handle resource)
handle)))))</code></pre>
<h2 id="implementation">Implementation</h2>
<p>A portable implementation of guardians is not possible. Chez Scheme provides guardians as explained in this SRFI; Guile provides them as well, but without <code>guardian-unregister</code>.</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Thanks to the members of the SRFI discussion group.</p>
<h2 id="copyright">Copyright</h2>
<p>© 2023 John Cowan.
This SRFI is a derivative work of <a href="https://cisco.github.io/ChezScheme/csug9.5/smgmt.html#./smgmt:h2">Section 13.2 of <i>Chez Scheme User's Guide version 9</i></a>, which is licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License Version 2.0</a>, © Cisco Systems, Inc. 2022. The SRFI as a whole is licensed as follows:</p>
<blockquote>
<p>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:</p>
<p>
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.</p>
</blockquote>
<hr>
<address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Arthur A. Gleckler</a></address></body></html>