(use-modules (tests) (ice-9 atomic) (ice-9 threads) (srfi srfi-71) (fibers) (unit-test) (knots) (knots thread-pool)) (let ((thread-pool (make-fixed-size-thread-pool 2))) (assert-equal (call-with-thread thread-pool (lambda () 4)) 4)) (let ((thread-pool (make-fixed-size-thread-pool 2 #:thread-initializer (const '(2))))) (assert-equal (call-with-thread thread-pool (lambda (num) (* 2 num))) 4)) (let ((thread-pool (make-fixed-size-thread-pool 2))) (assert-equal #t (with-exception-handler (lambda (exn) (knots-exception? exn)) (lambda () (call-with-thread thread-pool (lambda () (+ 1 'a)))) #:unwind? #t))) (run-fibers-for-tests (lambda () (let ((thread-pool (make-thread-pool 2))) (assert-equal (call-with-thread thread-pool (lambda () 4)) 4)))) (run-fibers-for-tests (lambda () (let ((thread-pool (make-thread-pool 2 #:thread-initializer (const '(2))))) (assert-equal (call-with-thread thread-pool (lambda (num) (* 2 num))) 4)))) (run-fibers-for-tests (lambda () (let ((thread-pool (make-thread-pool 2))) (assert-equal #t (with-exception-handler (lambda (exn) (knots-exception? exn)) (lambda () (call-with-thread thread-pool (lambda () (+ 1 'a)))) #:unwind? #t))))) (let ((thread-pool (make-fixed-size-thread-pool 1 #:thread-lifetime 1 #:thread-initializer (lambda () (list (make-atomic-box #t)))))) (for-each (lambda _ (call-with-thread thread-pool (lambda (box) (if (atomic-box-ref box) (atomic-box-set! box #f) (error (atomic-box-ref box)))))) (iota 10))) (run-fibers-for-tests (lambda () (let ((thread-pool (make-thread-pool 1 #:thread-lifetime 1))) (for-each (lambda _ (call-with-thread thread-pool (lambda () #f))) (iota 10))))) (let ((thread-pool (make-fixed-size-thread-pool 1 #:thread-lifetime 2 #:thread-initializer (lambda () (list (make-atomic-box 2)))))) (define (ref-and-decrement box) (let ((val (atomic-box-ref box))) (atomic-box-set! box (- val 1)) val)) (unless (= 2 (call-with-thread thread-pool ref-and-decrement)) (error)) (unless (= 1 (call-with-thread thread-pool ref-and-decrement)) (error)) (unless (= 2 (call-with-thread thread-pool ref-and-decrement)) (error))) ;; Test that the destructor is called when a size 1 fixed-size thread ;; pool is destroyed, and that destroy-thread-pool blocks until it has ;; completed. (let* ((destructor-called? #f) (thread-pool (make-fixed-size-thread-pool 1 #:thread-destructor (lambda () (set! destructor-called? #t))))) (destroy-thread-pool thread-pool) (assert-equal #t destructor-called?)) ;; Test that the destructor is called for every thread when a ;; multi-thread fixed-size thread pool is destroyed, and that ;; destroy-thread-pool blocks until all destructors have completed. (let* ((destructor-count 0) (mutex (make-mutex)) (pool-size 3) (thread-pool (make-fixed-size-thread-pool pool-size #:thread-destructor (lambda () (with-mutex mutex (set! destructor-count (+ destructor-count 1))))))) (destroy-thread-pool thread-pool) (assert-equal pool-size destructor-count)) ;; Test delay-logger and duration-logger for fixed-size thread pool (let* ((logged-delay #f) (logged-duration #f) (thread-pool (make-fixed-size-thread-pool 1 #:delay-logger (lambda (seconds) (set! logged-delay seconds)) #:duration-logger (lambda (seconds) (set! logged-duration seconds))))) (call-with-thread thread-pool (lambda () (usleep 100000))) (assert-true (number? logged-delay)) (assert-true (number? logged-duration)) (assert-true (>= logged-duration 0.1)) (destroy-thread-pool thread-pool)) ;; Test delay-logger and duration-logger for dynamic thread pool (run-fibers-for-tests (lambda () (let* ((logged-delay #f) (logged-duration #f) (thread-pool (make-thread-pool 1 #:delay-logger (lambda (seconds) (set! logged-delay seconds)) #:duration-logger (lambda (seconds) (set! logged-duration seconds))))) (call-with-thread thread-pool (lambda () (usleep 100000))) (assert-true (number? logged-delay)) (assert-true (number? logged-duration)) (assert-true (>= logged-duration 0.1)) (destroy-thread-pool thread-pool)))) (display "thread-pool test finished successfully\n")