timers.scm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. ;; Fibers: cooperative, event-driven user-space threads.
  2. ;;;; Copyright (C) 2016 Free Software Foundation, Inc.
  3. ;;;;
  4. ;;;; This library is free software; you can redistribute it and/or
  5. ;;;; modify it under the terms of the GNU Lesser General Public
  6. ;;;; License as published by the Free Software Foundation; either
  7. ;;;; version 3 of the License, or (at your option) any later version.
  8. ;;;;
  9. ;;;; This library is distributed in the hope that it will be useful,
  10. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;;; Lesser General Public License for more details.
  13. ;;;;
  14. ;;;; You should have received a copy of the GNU Lesser General Public
  15. ;;;; License along with this library; if not, write to the Free Software
  16. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;;;
  18. (define-module (fibers timers)
  19. #:use-module (fibers scheduler)
  20. #:use-module (fibers operations)
  21. #:use-module (ice-9 atomic)
  22. #:use-module (ice-9 match)
  23. #:use-module (ice-9 threads)
  24. #:export (sleep-operation
  25. timer-operation)
  26. #:replace (sleep))
  27. (define *timer-sched* (make-atomic-box #f))
  28. (define (timer-sched)
  29. (or (atomic-box-ref *timer-sched*)
  30. (let ((sched (make-scheduler)))
  31. (cond
  32. ((atomic-box-compare-and-swap! *timer-sched* #f sched))
  33. (else
  34. ;; FIXME: Would be nice to clean up this thread at some point.
  35. (call-with-new-thread
  36. (lambda ()
  37. (define (finished?) #f)
  38. (run-scheduler sched finished?)))
  39. sched)))))
  40. (define (timer-operation expiry)
  41. "Make an operation that will succeed when the current time is
  42. greater than or equal to @var{expiry}, expressed in internal time
  43. units. The operation will succeed with no values."
  44. (make-base-operation #f
  45. (lambda ()
  46. (and (< expiry (get-internal-real-time))
  47. values))
  48. (lambda (flag sched resume)
  49. (define (timer)
  50. (match (atomic-box-compare-and-swap! flag 'W 'S)
  51. ('W (resume values))
  52. ('C (timer))
  53. ('S #f)))
  54. (if sched
  55. (schedule-task-at-time sched expiry timer)
  56. (schedule-task
  57. (timer-sched)
  58. (lambda ()
  59. (perform-operation (timer-operation expiry))
  60. (timer)))))))
  61. (define (sleep-operation seconds)
  62. "Make an operation that will succeed with no values when
  63. @var{seconds} have elapsed."
  64. (timer-operation
  65. (+ (get-internal-real-time)
  66. (inexact->exact
  67. (round (* seconds internal-time-units-per-second))))))
  68. (define (sleep seconds)
  69. "Block the calling fiber until @var{seconds} have elapsed."
  70. (perform-operation (sleep-operation seconds)))