背景
前段时间实现了一个 call-with-tcp-listener 过程(函数)
(call-with-tcp-listener "127.0.0.1:8088" ( lambda (in) (
(display (req-read-string in))
"HTTP/1.1 200 OK\r\n\r\n hello word"
)))
如果是简单的返回数据还不存在问题,但是当涉及到io的时候就会出现阻塞的情况,最简单的解决方案就是一个请求一个线程,但是这种模型开销比较大,所以想到了线程池,然后就实现了一个及其简单的版本
实现
使用到了 thread + channel + lambda-lep + apply 这几个过程
首先定义一个线程池
async.lisp
(
(define thread-qty (* (get-os-cpu-num) 2))
(define thread-count 1)
(define barrier (make-barrier thread-qty))
(define channel (make-channel))
(while (< thread-count thread-qty)
(
(thread-run (lambda () (
(channel-for-each (lambda (task) (
( task)
)) channel)
(barrier-wait barrier)
;; (loop ((<- channel)))
)))
(set! thread-count (+ thread-count 1))))
(define go (lambda-lep (task) (
(apply (`(-> ,channel ,task)))
)))
(export go)
)
如何使用
(
(import (go) from "./async.lisp")
(go
(lambda ()
(println (current-thread-name) " hello rust-lisp!"))))
控制台会输出
thread-1 hello rust-lisp!
重构
让我们在结合 call-with-tcp-listener 过程完善一下吧
首先重构一下 call-with-tcp-listener 过程使其接受out port
main.lisp
(
(def handler (in out) (
;; 模拟io读取等待
(sleep 1)
(println (current-thread-name))
(display (req-read-string in))
(write-string "HTTP/1.1 200 OK\r\n\r\n hello word" out )
))
(call-with-tcp-listener "127.0.0.1:8088" ( lambda (in out) (
( handler in out)
))))
然后使用go 过程实现任务提交
main.lisp
(
(load "./lib.lisp")
(import (go) from "./async.lisp")
(def handler (in out) (
;; 模拟io读取等待
(sleep 1)
(println (current-thread-name))
(display (req-read-string in))
(write-string "HTTP/1.1 200 OK\r\n\r\n hello word" out )
))
(call-with-tcp-listener "127.0.0.1:8088" ( lambda (in out) (
(go (lambda () (handler in out)))
))))
任务提交之后,下面这段代码会从channel中读取到最新提交的 task (过程) 然后执行。
(channel-for-each (lambda (task) (
(task)
)) channel)
运行后访问 控制台打印如下
thread1
GET / HTTP/1.0
Host: 127.0.0.1:8088
User-Agent: ApacheBench/2.3
Accept: */*