Browse code
(init)
Ed Langley authored on 07/02/2019 01:21:47
Showing 6 changed files
Showing 6 changed files
- .gitignore
- chanl-event-loop.lisp
- event-loop.lisp
- fwoar-event-loop.asd
- package.lisp
- sbcl-concurrency-event-loop.lisp
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 | 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))))) |