git.fiddlerwoaroof.com
Browse code

(init)

Ed Langley authored on 07/02/2019 01:21:47
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+*~
2
+*.fasl
0 3
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+(in-package :fwoar.event-loop)
2
+
3
+(defclass chanl-event-loop ()
4
+  ((%queue :initarg :queue :reader queue :initform (make-instance 'chanl:bounded-channel :size *task-depth*))
5
+   (%finish-callbaack :reader finish-cb :writer register-finish-cb)))
6
+
7
+(defmethod tick ((event-loop chanl-event-loop))
8
+  (prog1 event-loop
9
+    (let ((task (chanl:recv (queue event-loop))))
10
+      (when task
11
+        (funcall task)))))
12
+
13
+(defmethod enqueue ((queue chanl:channel) fn)
14
+  (chanl:send queue fn))
0 15
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+(in-package :fwoar.event-loop)
2
+
3
+(defgeneric run (task event-loop)
4
+  (:method :around (task event-loop)
5
+    (bb:with-promise (resolve reject)
6
+      (enqueue (queue event-loop)
7
+               (lambda ()
8
+                 (handler-case (resolve (call-next-method))
9
+                   (serious-condition (c)
10
+                     (reject c))))))))
11
+
12
+
13
+(defgeneric enqueue (queue fn))
14
+
15
+(defgeneric prepare-loop (event-loop)
16
+  (:method (event-loop)
17
+    (declare (ignore event-loop))))
18
+
19
+(defgeneric queue (event-loop))
20
+
21
+(defgeneric register-finish-cb (cb event-loop))
22
+
23
+(defgeneric tick (event-loop))
24
+
25
+(defparameter *task-depth* 10)
26
+
27
+(defun run-loop (event-loop)
28
+  (let ((finished nil))
29
+    (register-finish-cb (lambda ()
30
+                          (setf finished t))
31
+                        event-loop)
32
+    (prepare-loop event-loop)
33
+    (loop
34
+      until finished
35
+      do
36
+         (tick event-loop))))
37
+
38
+(defun wait-for-promise (promise)
39
+  (let* ((result-queue (make-instance 'chanl:bounded-channel)))
40
+    (bb:alet ((v promise))
41
+      (chanl:send result-queue v))
42
+    (loop
43
+      (return (chanl:recv result-queue)))))
0 44
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; Package: ASDF-USER -*-
2
+(in-package :asdf-user)
3
+
4
+(defsystem :fwoar-event-loop 
5
+  :description ""
6
+  :author "Ed L <edward@elangley.org>"
7
+  :license "MIT"
8
+  :depends-on (#:alexandria
9
+               #:blackbird
10
+               #:chanl
11
+               #:serapeum
12
+               #:uiop
13
+               (:feature :sbcl
14
+                         (:require :sb-concurrency)))
15
+  :serial t
16
+  :components ((:file "package")
17
+               (:file "event-loop")
18
+               (:file "chanl-event-loop")
19
+               (:file "sbcl-concurrency-event-loop" :if-feature :sbcl)))
0 20
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+(defpackage :fwoar.event-loop
2
+  (:use :cl )
3
+  (:export
4
+   #:run
5
+   #:tick
6
+   #:run-loop
7
+   #:wait-for-promise
8
+   #:prepare-loop
9
+   #:register-finish-cb))
0 10
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+(in-package :fwoar.event-loop)
2
+
3
+(defclass sb-concurrency-event-loop ()
4
+  ((%queue :initarg :queue :reader queue :initform (sb-concurrency:make-mailbox))
5
+   (%finish-callbaack :reader finish-cb :writer register-finish-cb)))
6
+
7
+(defmethod enqueue ((queue sb-concurrency:mailbox) fn)
8
+  (sb-concurrency:send-message queue fn))
9
+
10
+(defmethod tick ((event-loop sb-concurrency-event-loop))
11
+  (prog1 event-loop
12
+    (let ((task (sb-concurrency:receive-message (queue event-loop) :timeout 0.001)))
13
+      (when task
14
+        (funcall task)))))