("fixart" . (RUNTIME FIXNUM-ARITHMETIC))
("random" . (RUNTIME RANDOM-NUMBER))
("gentag" . (RUNTIME GENERIC-PROCEDURE))
- ("poplat" . (RUNTIME POPULATION))
("record" . (RUNTIME RECORD))))
(files2
'(("syntax-items" . (RUNTIME SYNTAX ITEMS))
("syntax-transforms" . (RUNTIME SYNTAX TRANSFORMS))
+ ("poplat" . (RUNTIME POPULATION))
+ ("thread" . (RUNTIME THREAD))
("prop1d" . (RUNTIME 1D-PROPERTY))
("events" . (RUNTIME EVENT-DISTRIBUTOR))
("gdatab" . (RUNTIME GLOBAL-DATABASE))
("vector" . (RUNTIME VECTOR))
- ("thread" . (RUNTIME THREAD))
("wind" . (RUNTIME WIND))
("gcfinal" . (RUNTIME GC-FINALIZER))
("string" . (RUNTIME STRING)) ; First GC-finalizer.
(package-initialize '(RUNTIME RANDOM-NUMBER) #f #t)
(package-initialize '(RUNTIME GENERIC-PROCEDURE) 'INITIALIZE-TAG-CONSTANTS!
#t)
- (package-initialize '(RUNTIME POPULATION) #f #t)
(package-initialize '(RUNTIME RECORD) 'INITIALIZE-RECORD-TYPE-TYPE! #t)
(load-files files2)
- (package-initialize '(RUNTIME 1D-PROPERTY) #f #t)
+ (package-initialize '(RUNTIME POPULATION) #f #t)
+ (package-initialize '(RUNTIME 1D-PROPERTY) #f #t) ;First population.
+ (package-initialize '(RUNTIME THREAD) 'INITIALIZE-LOW! #t) ;First 1d-table.
(package-initialize '(RUNTIME EVENT-DISTRIBUTOR) #f #t)
(package-initialize '(RUNTIME GLOBAL-DATABASE) #f #t)
(package-initialize '(RUNTIME POPULATION) 'INITIALIZE-UNPARSER! #t)
(package-initialize '(RUNTIME 1D-PROPERTY) 'INITIALIZE-UNPARSER! #t)
- (package-initialize '(RUNTIME THREAD) 'INITIALIZE-LOW! #t)
(package-initialize '(RUNTIME GC-FINALIZER) #f #t)
(package-initialize '(RUNTIME STRING) #f #t)
(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-locked (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-locked (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-locked (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-locked (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
value)))
\f
(define-structure (thread
- (constructor %make-thread ())
+ (constructor %make-thread (properties))
(conc-name thread/))
(execution-state 'RUNNING)
;; One of:
;; List of mutexes that this thread owns or is waiting to own. Used
;; to disassociate the thread from those mutexes when it is exited.
- (properties (make-1d-table) read-only #t))
+ (properties #f read-only #t))
(define-integrable (guarantee-thread thread procedure)
(if (not (thread? thread))
(define (initialize-low!)
;; Called early in the cold load to create the first thread.
- (set! thread-population (make-population))
+ (set! thread-population (make-population/unsafe))
(set! first-runnable-thread #f)
(set! last-runnable-thread #f)
(set! next-scheduled-timeout #f)
(set! timer-records #f)
(set! timer-interval 100)
(reset-threads-low!)
- (let ((first (%make-thread)))
+ (let ((first (%make-thread (make-1d-table/unsafe))))
(set-thread/exit-value! first detached-thread-marker)
- (add-to-population!/unsafe thread-population first)
+ (add-to-population! thread-population first)
(vector-set! current-threads
(if enable-smp?
((ucode-primitive smp-id 0))
(lambda ()
(call-with-current-continuation
(lambda (continuation)
- (let ((thread (%make-thread)))
+ (let ((thread (%make-thread (make-1d-table))))
(set-thread/continuation! thread continuation)
(with-threads-locked
(lambda ()
- (add-to-population!/unsafe thread-population thread)
+ (add-to-population! thread-population thread)
(thread-running (%id) thread)))
(%within-continuation (let ((k return)) (set! return #f) k)
#t