racket/base: add `impersonator-ephemeron'

This commit is contained in:
Matthew Flatt 2013-02-18 16:16:07 -07:00
parent d46411d317
commit 79c4af4e45
8 changed files with 601 additions and 544 deletions

View File

@ -110,6 +110,16 @@ Otherwise, all chaperones of @racket[v2] must be intact in
from @racket[v1] through one of the chaperone constructors (e.g.,
@racket[chaperone-procedure]).}
@defproc[(impersonator-ephemeron [v any/c]) ephemeron?]{
Produces an @tech{ephemeron} that can be used to connect the
reachability of @racket[v] (in the sense of garbage collection; see
@secref["gc-model"]) with the reachability of any value for which
@racket[v] is an @tech{impersonator}. That is, the value @racket[v]
will be considered reachable as long as the result ephemeron is
reachable in addition to any value that @racket[v] impersonates
(including itself).}
@; ------------------------------------------------------------
@section{Impersonator Constructors}

View File

@ -13,7 +13,7 @@ A @deftech{weak box} is similar to a normal box (see
only reachable via weak references, the content of the weak box is
replaced with @racket[#f]. A @defterm{@tech{weak reference}} is a
reference through a weak box, through a key reference in a weak hash
table (see @secref["hashtables"]), through a value in an ephemeron
table (see @secref["hashtables"]), through a value in an @tech{ephemeron}
where the value can be replaced by @racket[#f] (see
@secref["ephemerons"]), or through a custodian (see
@secref["custodians"]).
@ -56,7 +56,9 @@ are the same.
One particularly common use of ephemerons is to combine them with a
weak hash table (see @secref["hashtables"]) to produce a mapping where
the memory manager can reclaim key--value pairs even when the value
refers to the key.
refers to the key. A related use is to retain a reference to a value
as long as any value for which it is an @tech{impersonator} is
reachable; see @racket[impersonator-ephemeron].
More precisely,
@itemize[

View File

@ -1314,6 +1314,29 @@
o)
(test #"(a #0=(a #0#))" get-output-bytes o)))
;; ----------------------------------------
;; Impersonators and ephemerons:
(let ()
(define stuff
(for/list ([n 100])
(define v (vector n))
(define c (chaperone-vector v
(lambda (b i v) v)
(lambda (b i v) v)))
(define e (impersonator-ephemeron c))
(test c ephemeron-value e)
;; hold on to every other vector:
(cons e (if (even? n) v #f))))
(collect-garbage)
(define n (for/fold ([n 0]) ([p stuff])
(+ n
;; add 1 if should-retained != is-retained
(if (ephemeron-value (car p))
(if (vector? (cdr p)) 0 1)
(if (vector? (cdr p)) 1 0)))))
(test #t < n 50))
;; ----------------------------------------
(report-errs)

View File

@ -1,3 +1,6 @@
Version 5.3.3.4
Added impersonator-ephemeron
Version 5.3.3.3
ffi/unsafe: added _size, _ssize, _ptrdiff, _intmax, _uintmax
ffi/vector: added f8vectors

File diff suppressed because it is too large Load Diff

View File

@ -145,6 +145,7 @@ static Scheme_Object *weak_boxp(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_ephemeron(int argc, Scheme_Object *argv[]);
static Scheme_Object *ephemeron_value(int argc, Scheme_Object *argv[]);
static Scheme_Object *ephemeronp(int argc, Scheme_Object *argv[]);
static Scheme_Object *impersonator_ephemeron(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_graph(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_placeholder(int argc, Scheme_Object *argv[]);
@ -693,6 +694,11 @@ scheme_init_list (Scheme_Env *env)
"ephemeron?",
1, 1, 1),
env);
scheme_add_global_constant("impersonator-ephemeron",
scheme_make_immed_prim(impersonator_ephemeron,
"impersonator-ephemeron",
1, 1),
env);
scheme_add_global_constant("make-reader-graph",
scheme_make_prim_w_arity(make_graph,
@ -3551,6 +3557,19 @@ static Scheme_Object *ephemeronp(int argc, Scheme_Object *argv[])
: scheme_false);
}
static Scheme_Object *impersonator_ephemeron(int argc, Scheme_Object *argv[])
{
Scheme_Object *obj = argv[0];
if (SCHEME_CHAPERONEP(obj)) {
return scheme_make_ephemeron(SCHEME_CHAPERONE_VAL(obj), obj);
} else {
/* This is a useless ephemeron, but we create one for consistency
with the case that we have an impersonator: */
return scheme_make_ephemeron(obj, obj);
}
}
#ifndef MZ_PRECISE_GC
int scheme_propagate_ephemeron_marks()

View File

@ -14,7 +14,7 @@
#define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 1086
#define EXPECTED_PRIM_COUNT 1087
#define EXPECTED_UNSAFE_COUNT 100
#define EXPECTED_FLFXNUM_COUNT 69
#define EXPECTED_EXTFL_COUNT 45

View File

@ -13,12 +13,12 @@
consistently.)
*/
#define MZSCHEME_VERSION "5.3.3.3"
#define MZSCHEME_VERSION "5.3.3.4"
#define MZSCHEME_VERSION_X 5
#define MZSCHEME_VERSION_Y 3
#define MZSCHEME_VERSION_Z 3
#define MZSCHEME_VERSION_W 3
#define MZSCHEME_VERSION_W 4
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)