(declare (usual-integrations))
\f
-;;; A population is a collection of objects. This collection has the
-;;; property that if one of the objects in the collection is reclaimed
-;;; as garbage, then it is no longer an element of the collection.
+;;; A population is a weak collection of objects. A serial
+;;; population is a population with a mutex to serialize its operations.
(define (initialize-package!)
- (set! population-of-populations (cons population-tag '()))
- (add-secondary-gc-daemon! gc-all-populations!))
+ (set! population-of-populations (list population-tag (make-thread-mutex)))
+ (add-secondary-gc-daemon! clean-all-populations!))
(define (initialize-unparser!)
(unparser/set-tagged-pair-method! population-tag
(define bogus-false '(BOGUS-FALSE))
(define population-tag '(POPULATION))
-(define-integrable weak-cons-type (ucode-type weak-cons))
(define-integrable (canonicalize object)
(if (eq? object false) bogus-false object))
(define-integrable (uncanonicalize object)
(if (eq? object bogus-false) false object))
-(define (gc-population! population)
- (let loop ((l1 population) (l2 (cdr population)))
+(define (clean-population! population)
+ (if (cadr population)
+ (with-thread-mutex-lock (cadr population)
+ (lambda ()
+ (%clean-population! population)))
+ (%clean-population! population)))
+
+(define (%clean-population! population)
+ (let loop ((l1 (cdr population)) (l2 (cddr population)))
(cond ((null? l2) true)
((eq? (system-pair-car l2) false)
(system-pair-set-cdr! l1 (system-pair-cdr l2))
- (loop l1 (system-pair-cdr l1)))
+ (loop l1 (system-pair-cdr l2)))
(else (loop l2 (system-pair-cdr l2))))))
-(define (gc-all-populations!)
- (gc-population! population-of-populations)
- (map-over-population! population-of-populations gc-population!))
+(define (clean-all-populations!)
+ (clean-population! population-of-populations)
+ (map-over-population! population-of-populations clean-population!))
(define population-of-populations)
\f
(define (make-population)
- (let ((population (cons population-tag '())))
+ (let ((population (list population-tag #f)))
+ (add-to-population! population-of-populations population)
+ population))
+
+(define (make-population/unsafe)
+ (let ((population (list population-tag #f)))
+ (add-to-population!/unsafe population-of-populations population)
+ population))
+
+(define (make-serial-population)
+ (let ((population (list population-tag (make-thread-mutex))))
(add-to-population! population-of-populations population)
population))
+(define (make-serial-population/unsafe)
+ (let ((population (list population-tag (make-thread-mutex))))
+ (add-to-population!/unsafe population-of-populations population)
+ population))
+
(define (population? object)
(and (pair? object)
(eq? (car object) population-tag)))
-(define (add-to-population!/unsafe population object)
- (set-cdr! population
- (system-pair-cons weak-cons-type
- (canonicalize object)
- (cdr population))))
+(define-guarantee population "population")
(define (add-to-population! population object)
+ (guarantee-population population 'add-to-population!)
+ (if (cadr population)
+ (with-thread-mutex-lock (cadr population)
+ (lambda ()
+ (%add-to-population! population object)))
+ (%add-to-population! population object)))
+
+(define (%add-to-population! population object)
(let ((object (canonicalize object)))
- (let loop ((previous population) (this (cdr population)))
+ (let loop ((previous (cdr population)) (this (cddr population)))
(if (null? this)
- (set-cdr! population
- (system-pair-cons weak-cons-type
- object
- (cdr population)))
+ (set-cdr! (cdr population)
+ (weak-cons object (cddr population)))
(let ((entry (system-pair-car this))
(next (system-pair-cdr this)))
(cond ((not entry)
((not (eq? object entry))
(loop this next))))))))
+(define (add-to-population!/unsafe population object)
+ ;; No canonicalization, no uniquification, no locking.
+ (set-cdr! (cdr population) (weak-cons object (cddr population))))
+
(define (remove-from-population! population object)
+ (guarantee-population population 'remove-from-population!)
+ (if (cadr population)
+ (with-thread-mutex-lock (cadr population)
+ (lambda ()
+ (%remove-from-population! population object)))
+ (%remove-from-population! population object)))
+
+(define (%remove-from-population! population object)
(let ((object (canonicalize object)))
- (let loop ((previous population) (this (cdr population)))
+ (let loop ((previous (cdr population)) (this (cddr population)))
(if (not (null? this))
(let ((entry (system-pair-car this))
(next (system-pair-cdr this)))
(begin (system-pair-set-cdr! previous next)
(loop previous next))
(loop this next)))))))
+
+(define (empty-population! population)
+ (guarantee-population population 'empty-population!)
+ (if (cadr population)
+ (with-thread-mutex-lock (cadr population)
+ (lambda ()
+ (%empty-population! population)))
+ (%empty-population! population)))
+
+(define (%empty-population! population)
+ (set-cdr! (cdr population) '()))
\f
-;;;; Higher level operations
+;;;; Read-only operations
+
+;;; These are safe without serialization.
(define (map-over-population population procedure)
- (let loop ((l1 population) (l2 (cdr population)))
+ (let loop ((l2 (cddr population)))
(cond ((null? l2) '())
((eq? (system-pair-car l2) false)
- (system-pair-set-cdr! l1 (system-pair-cdr l2))
- (loop l1 (system-pair-cdr l1)))
+ (loop (system-pair-cdr l2)))
(else
(cons (procedure (uncanonicalize (system-pair-car l2)))
- (loop l2 (system-pair-cdr l2)))))))
+ (loop (system-pair-cdr l2)))))))
(define (map-over-population! population procedure)
- (let loop ((l1 population) (l2 (cdr population)))
+ (let loop ((l2 (cddr population)))
(cond ((null? l2) true)
((eq? (system-pair-car l2) false)
- (system-pair-set-cdr! l1 (system-pair-cdr l2))
- (loop l1 (system-pair-cdr l1)))
+ (loop (system-pair-cdr l2)))
(else
(procedure (uncanonicalize (system-pair-car l2)))
- (loop l2 (system-pair-cdr l2))))))
+ (loop (system-pair-cdr l2))))))
(define (for-all-inhabitants? population predicate)
- (let loop ((l1 population) (l2 (cdr population)))
+ (let loop ((l2 (cddr population)))
(or (null? l2)
(if (eq? (system-pair-car l2) false)
- (begin (system-pair-set-cdr! l1 (system-pair-cdr l2))
- (loop l1 (system-pair-cdr l1)))
+ (loop (system-pair-cdr l2))
(and (predicate (uncanonicalize (system-pair-car l2)))
- (loop l2 (system-pair-cdr l2)))))))
+ (loop (system-pair-cdr l2)))))))
(define (exists-an-inhabitant? population predicate)
- (let loop ((l1 population) (l2 (cdr population)))
+ (let loop ((l2 (cddr population)))
(and (not (null? l2))
(if (eq? (system-pair-car l2) false)
- (begin (system-pair-set-cdr! l1 (system-pair-cdr l2))
- (loop l1 (system-pair-cdr l1)))
+ (loop (system-pair-cdr l2))
(or (predicate (uncanonicalize (system-pair-car l2)))
- (loop l2 (system-pair-cdr l2)))))))
\ No newline at end of file
+ (loop (system-pair-cdr l2)))))))
\ No newline at end of file