threads.test 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. ;;;; threads.test --- Tests for Guile threading. -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright 2003, 2006 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This program is free software; you can redistribute it and/or modify
  6. ;;;; it under the terms of the GNU General Public License as published by
  7. ;;;; the Free Software Foundation; either version 2, or (at your option)
  8. ;;;; any later version.
  9. ;;;;
  10. ;;;; This program is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;;;; GNU General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU General Public License
  16. ;;;; along with this software; see the file COPYING. If not, write to
  17. ;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. ;;;; Boston, MA 02110-1301 USA
  19. (use-modules (ice-9 threads)
  20. (test-suite lib))
  21. (if (provided? 'threads)
  22. (begin
  23. (with-test-prefix "parallel"
  24. (pass-if "no forms"
  25. (call-with-values
  26. (lambda ()
  27. (parallel))
  28. (lambda ()
  29. #t)))
  30. (pass-if "1"
  31. (call-with-values
  32. (lambda ()
  33. (parallel 1))
  34. (lambda (x)
  35. (equal? x 1))))
  36. (pass-if "1 2"
  37. (call-with-values
  38. (lambda ()
  39. (parallel 1 2))
  40. (lambda (x y)
  41. (and (equal? x 1)
  42. (equal? y 2)))))
  43. (pass-if "1 2 3"
  44. (call-with-values
  45. (lambda ()
  46. (parallel 1 2 3))
  47. (lambda (x y z)
  48. (and (equal? x 1)
  49. (equal? y 2)
  50. (equal? z 3))))))
  51. ;;
  52. ;; n-par-for-each
  53. ;;
  54. (with-test-prefix "n-par-for-each"
  55. (pass-if "0 in limit 10"
  56. (n-par-for-each 10 noop '())
  57. #t)
  58. (pass-if "6 in limit 10"
  59. (let ((v (make-vector 6 #f)))
  60. (n-par-for-each 10 (lambda (n)
  61. (vector-set! v n #t))
  62. '(0 1 2 3 4 5))
  63. (equal? v '#(#t #t #t #t #t #t))))
  64. (pass-if "6 in limit 1"
  65. (let ((v (make-vector 6 #f)))
  66. (n-par-for-each 1 (lambda (n)
  67. (vector-set! v n #t))
  68. '(0 1 2 3 4 5))
  69. (equal? v '#(#t #t #t #t #t #t))))
  70. (pass-if "6 in limit 2"
  71. (let ((v (make-vector 6 #f)))
  72. (n-par-for-each 2 (lambda (n)
  73. (vector-set! v n #t))
  74. '(0 1 2 3 4 5))
  75. (equal? v '#(#t #t #t #t #t #t))))
  76. (pass-if "6 in limit 3"
  77. (let ((v (make-vector 6 #f)))
  78. (n-par-for-each 3 (lambda (n)
  79. (vector-set! v n #t))
  80. '(0 1 2 3 4 5))
  81. (equal? v '#(#t #t #t #t #t #t)))))
  82. ;;
  83. ;; n-for-each-par-map
  84. ;;
  85. (with-test-prefix "n-for-each-par-map"
  86. (pass-if "0 in limit 10"
  87. (n-for-each-par-map 10 noop noop '())
  88. #t)
  89. (pass-if "6 in limit 10"
  90. (let ((result '()))
  91. (n-for-each-par-map 10
  92. (lambda (n) (set! result (cons n result)))
  93. (lambda (n) (* 2 n))
  94. '(0 1 2 3 4 5))
  95. (equal? result '(10 8 6 4 2 0))))
  96. (pass-if "6 in limit 1"
  97. (let ((result '()))
  98. (n-for-each-par-map 1
  99. (lambda (n) (set! result (cons n result)))
  100. (lambda (n) (* 2 n))
  101. '(0 1 2 3 4 5))
  102. (equal? result '(10 8 6 4 2 0))))
  103. (pass-if "6 in limit 2"
  104. (let ((result '()))
  105. (n-for-each-par-map 2
  106. (lambda (n) (set! result (cons n result)))
  107. (lambda (n) (* 2 n))
  108. '(0 1 2 3 4 5))
  109. (equal? result '(10 8 6 4 2 0))))
  110. (pass-if "6 in limit 3"
  111. (let ((result '()))
  112. (n-for-each-par-map 3
  113. (lambda (n) (set! result (cons n result)))
  114. (lambda (n) (* 2 n))
  115. '(0 1 2 3 4 5))
  116. (equal? result '(10 8 6 4 2 0)))))
  117. ;;
  118. ;; thread joining
  119. ;;
  120. (with-test-prefix "joining"
  121. ;; scm_join_thread has a SCM_TICK in the middle of it, to
  122. ;; allow asyncs to run (including signal delivery). We used
  123. ;; to have a bug whereby if the joined thread terminated at
  124. ;; the same time as the joining thread is in this SCM_TICK,
  125. ;; scm_join_thread would not notice and would hang forever.
  126. ;; So in this test we are setting up the following sequence of
  127. ;; events.
  128. ;; T=0 other thread is created and starts running
  129. ;; T=2 main thread sets up an async that will sleep for 10 seconds
  130. ;; T=2 main thread calls join-thread, which will...
  131. ;; T=2 ...call the async, which starts sleeping
  132. ;; T=5 other thread finishes its work and terminates
  133. ;; T=7 async completes, main thread continues inside join-thread.
  134. (pass-if "don't hang when joined thread terminates in SCM_TICK"
  135. (let ((other-thread (make-thread sleep 5)))
  136. (letrec ((delay-count 10)
  137. (aproc (lambda ()
  138. (set! delay-count (- delay-count 1))
  139. (if (zero? delay-count)
  140. (sleep 5)
  141. (system-async-mark aproc)))))
  142. (sleep 2)
  143. (system-async-mark aproc)
  144. (join-thread other-thread)))
  145. #t))))