summaryrefslogtreecommitdiff
path: root/fibers.scm
blob: 63873bd8b2411d942cfd0a4ead2d487050b14471 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
;; Fibers: cooperative, event-driven user-space threads.

;;;; Copyright (C) 2016 Free Software Foundation, Inc.
;;;; 
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;; 
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;; 
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;;; 

(define-module (fibers)
  #:use-module (fibers internal)
  #:use-module (fibers repl)
  #:use-module (fibers timers)
  #:use-module ((ice-9 ports internal)
                #:select (port-read-wait-fd port-write-wait-fd))
  #:use-module (ice-9 suspendable-ports)
  #:export (run-fibers
            spawn-fiber)
  #:re-export (current-fiber
               sleep))

(define (wait-for-readable port)
  (suspend-current-fiber
   (lambda (fiber)
     (resume-on-readable-fd (port-read-wait-fd port) fiber))))
(define (wait-for-writable port)
  (suspend-current-fiber
   (lambda (fiber)
     (resume-on-writable-fd (port-read-wait-fd port) fiber))))

(define* (run-fibers #:optional (init #f)
                     #:key (scheduler (make-scheduler))
                     (install-suspendable-ports? #t)
                     (keep-scheduler? (eq? scheduler (current-scheduler))))
  (when install-suspendable-ports? (install-suspendable-ports!))
  (with-scheduler
   scheduler
   (parameterize ((current-read-waiter wait-for-readable)
                  (current-write-waiter wait-for-writable))
     (let ((ret #f))
       (spawn-fiber (lambda ()
                      (call-with-values (or init values)
                        (lambda vals (set! ret vals))))
                    scheduler)
       (let lp ()
         (run-scheduler scheduler)
         (unless ret (lp)))
       (unless keep-scheduler? (destroy-scheduler scheduler))
       (apply values ret)))))

(define (require-current-scheduler)
  (or (current-scheduler)
      (error "No scheduler current; call within run-fibers instead")))

(define* (spawn-fiber thunk #:optional (sched (require-current-scheduler)))
  (create-fiber sched thunk))