Well that's a lot simpler

This commit is contained in:
Vivianne 2024-09-11 22:32:20 -04:00
parent 78a5d3577c
commit 7924fd14d9
2 changed files with 10 additions and 41 deletions

View file

@ -1,7 +1,7 @@
* Guile Weak References
This is a simple little library that makes use of the weak hash table functionality in core Guile
to hackily implement weak references, objects which weakly point to other objects.
This is a simple little library that makes use of the weak vector functionality in core Guile
to implement weak references, objects which weakly point to other objects.
The interface is very simple:
@ -12,11 +12,6 @@ The interface is very simple:
- Get the object associated with the reference, or #f if it has been garbage collected.
** Implementation
This is a very simple implementation. There's a globally incremented ID associated with each object, and
the object is stored in two global weak hash tables, one id-to-object and another object-to-id. The weak
reference is a record type that stores the ID and also a tombstone property to cache whether the object
has been collected to avoid the need to look it up after that point.
I created this because I needed an interface outside of the hash tables to refer to single objects instead
of creating a bunch of weak dictionaries. Also, Guile Hoot does not yet support iteration through weak key
hash tables, so this will allow me to create a list of weak refs to iterate over instead.
This is a very simple implementation (thanks David Thompson for a simpler idea). It simply calls a single-
element weak vector a weak reference. Initially this used the weak hash table support but using a weak
vector is far simpler and uses less memory.

View file

@ -1,40 +1,14 @@
(define-module (weakref)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-64)
#:use-module (ice-9 weak-vector)
#:export (make-weakref
weakref?
weakref-object))
(define *next-id* 0)
(define *ids-to-objects* (make-weak-value-hash-table))
(define *objects-to-ids* (make-weak-key-hash-table))
(define-record-type <weakref>
(_make-weakref id tombstone)
weakref?
(id weakref-id)
(tombstone weakref-tombstone set-weakref-tombstone!))
(set-record-type-printer!
<weakref>
(lambda (ref port)
(format port "#<weakref: ~a id=~a>" (or (weakref-object ref) "[gone]") (weakref-id ref))))
(define (weakref? obj)
(and (weak-vector? obj) (= 1 (vector-length obj))))
(define (make-weakref obj)
(_make-weakref
(or (hashq-ref *objects-to-ids* obj)
(let ((id *next-id*))
(set! *next-id* (1+ *next-id*))
(hashq-set! *ids-to-objects* id obj)
(hashq-set! *objects-to-ids* obj id)
id))
#f))
(make-weak-vector 1 obj))
(define (weakref-object ref)
(if (weakref-tombstone ref)
#f
(or (hashq-ref *ids-to-objects* (weakref-id ref))
(begin
(set-weakref-tombstone! ref #t)
#f))))
(weak-vector-ref ref 0))