repeated-condition.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. ;; This file is part of scheme-GNUnet.
  2. ;; Copyright (C) 2021 Maxime Devos
  3. ;;
  4. ;; scheme-GNUnet is free software: you can redistribute it and/or modify it
  5. ;; under the terms of the GNU Affero General Public License as published
  6. ;; by the Free Software Foundation, either version 3 of the License,
  7. ;; or (at your option) any later version.
  8. ;;
  9. ;; scheme-GNUnet is distributed in the hope that it will be useful, but
  10. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Affero General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Affero General Public License
  15. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;;
  17. ;; SPDX-License-Identifier: AGPL3.0-or-later
  18. (import (gnu gnunet concurrency repeated-condition)
  19. (gnu gnunet utils hat-let)
  20. (fibers operations)
  21. (fibers conditions)
  22. (fibers timers)
  23. (fibers)
  24. (srfi srfi-43))
  25. ;; Copied from 'tests/update.scm'.
  26. ;; TODO abstract this?
  27. (define expected-blocking-operation
  28. (wrap-operation (sleep-operation 1e-4)
  29. (lambda () 'blocking)))
  30. ;; First some basic sequential tests, ignoring memory ordering
  31. ;; issues and other concurrency.
  32. (test-begin "repeated condition")
  33. (test-assert "repeated conditions are condition?"
  34. (repeated-condition? (make-repeated-condition)))
  35. (test-equal "initially, await-trigger! blocks"
  36. '(blocking)
  37. (let^ ((<-- (rcvar) (make-repeated-condition))
  38. (<-- (operation) (prepare-await-trigger! rcvar)))
  39. (call-with-values
  40. (lambda ()
  41. (perform-operation
  42. (choice-operation operation expected-blocking-operation)))
  43. list)))
  44. (test-assert "trigger-condition! & await-trigger! completes, sequential"
  45. (let^ ((<-- (rcvar) (make-repeated-condition))
  46. (<-- () (trigger-condition! rcvar))
  47. (<-- () (await-trigger! rcvar)))
  48. #t))
  49. (test-assert "likewise, but multiple times"
  50. (let^ ((<-- (rcvar) (make-repeated-condition))
  51. (/o/ loop (todo 10))
  52. (<-- () (trigger-condition! rcvar))
  53. (<-- () (await-trigger! rcvar))
  54. (? (> todo 1)
  55. (loop (- todo 1))))
  56. #t))
  57. (test-assert "likewise, but prepare awaiting the trigger before triggering"
  58. (let^ ((<-- (rcvar) (make-repeated-condition))
  59. (<-- (operation) (prepare-await-trigger! rcvar))
  60. (<-- () (trigger-condition! rcvar))
  61. (<-- () (perform-operation operation)))
  62. #t))
  63. ;; This is a departure from fiber's conditions:
  64. ;; ‘repeated conditions’ are re-usable.
  65. (test-equal "await-trigger! hangs the second time (without trigger-condition!)"
  66. '(blocking)
  67. (let^ ((<-- (rcvar) (make-repeated-condition))
  68. (<-- () (trigger-condition! rcvar))
  69. (<-- () (await-trigger! rcvar))
  70. (<-- (operation) (prepare-await-trigger! rcvar)))
  71. (call-with-values
  72. (lambda ()
  73. (perform-operation
  74. (choice-operation operation expected-blocking-operation)))
  75. list)))
  76. ;; Now some concurrency tests.
  77. ;;
  78. ;; This test was meant to detect the absence of
  79. ;; (? (not next-old) (spin next-old)))
  80. ;;
  81. ;; but I didn't ever notice 'spin' being run.
  82. ;; (Try adding a 'pk' before 'spin').
  83. (test-assert "concurrent ping pong completes"
  84. (let^ ((! n/games 400)
  85. (! n/rounds 500)
  86. (! game/done?
  87. (vector-unfold (lambda (_) (make-condition)) n/games))
  88. (! start? (make-condition))
  89. (! (run-game done?)
  90. ;; In each round, concurrently ‘await’
  91. ;; and ‘trigger’ the condition. The result
  92. ;; should be that the round eventually
  93. ;; is completed.
  94. (let^ ((! rcvar (make-repeated-condition))
  95. (/o/ loop (round 0))
  96. (! (next-round) (loop (+ round 1)))
  97. (? (= round n/rounds)
  98. (signal-condition! done?))
  99. (! start-round? (make-condition))
  100. (! awaiter-done? (make-condition))
  101. (! trigger-done? (make-condition))
  102. (<-- ()
  103. (spawn-fiber
  104. (lambda ()
  105. (wait start-round?)
  106. (await-trigger! rcvar)
  107. (signal-condition! awaiter-done?))))
  108. (<-- ()
  109. (spawn-fiber
  110. (lambda ()
  111. (wait start-round?)
  112. (trigger-condition! rcvar)
  113. (signal-condition! trigger-done?))))
  114. (<-- (_) (signal-condition! start-round?))
  115. (<-- () (wait awaiter-done?))
  116. (<-- () (wait trigger-done?)))
  117. (next-round)))
  118. (! (spawn-game _ done?)
  119. (spawn-fiber
  120. (lambda ()
  121. (wait start?)
  122. (run-game done?)))))
  123. (run-fibers
  124. (lambda ()
  125. (vector-for-each spawn-game game/done?)
  126. (signal-condition! start?)
  127. (vector-for-each (lambda (_ c) (wait c)) game/done?)
  128. #t)
  129. #:hz 6000)))
  130. (test-end "repeated condition")