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 * Guile Weak References
This is a simple little library that makes use of the weak hash table functionality in core Guile This is a simple little library that makes use of the weak vector functionality in core Guile
to hackily implement weak references, objects which weakly point to other objects. to implement weak references, objects which weakly point to other objects.
The interface is very simple: 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. - Get the object associated with the reference, or #f if it has been garbage collected.
** Implementation ** Implementation
This is a very simple implementation. There's a globally incremented ID associated with each object, and This is a very simple implementation (thanks David Thompson for a simpler idea). It simply calls a single-
the object is stored in two global weak hash tables, one id-to-object and another object-to-id. The weak element weak vector a weak reference. Initially this used the weak hash table support but using a weak
reference is a record type that stores the ID and also a tombstone property to cache whether the object vector is far simpler and uses less memory.
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.

View file

@ -1,40 +1,14 @@
(define-module (weakref) (define-module (weakref)
#:use-module (srfi srfi-9) #:use-module (ice-9 weak-vector)
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-64)
#:export (make-weakref #:export (make-weakref
weakref? weakref?
weakref-object)) weakref-object))
(define *next-id* 0) (define (weakref? obj)
(define *ids-to-objects* (make-weak-value-hash-table)) (and (weak-vector? obj) (= 1 (vector-length obj))))
(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 (make-weakref obj) (define (make-weakref obj)
(_make-weakref (make-weak-vector 1 obj))
(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))
(define (weakref-object ref) (define (weakref-object ref)
(if (weakref-tombstone ref) (weak-vector-ref ref 0))
#f
(or (hashq-ref *ids-to-objects* (weakref-id ref))
(begin
(set-weakref-tombstone! ref #t)
#f))))