协作线程,无分配
Cooperative Threading, No assignment
作为序言,我喜欢自己滚动,这是一个以学习为目的的练习,但我最终想从这个练习中获取信息,并在此处实现一些封装行为的宏。这就是为什么我使用了很多 let
因为还没有最终确定并且定义太 "heavy".
所以你可以使用call/cc来实现各种不同的协作线程结构,我使用的线程模型通常是:
(let ((generic-thread
(lambda (cc)
(let loop ((cc cc))
(printf "doing stuff~N")
(loop (call/cc cc)))))) ;this is the magic, it calls the calling continuation
(let loop ((its 0) ;and then loops with the result of that
(cc generic-thread)) ;so when its resumed, it still has its new state
(if (< its 10)
(loop (+ its 1) (call/cc cc))))) ;just repeats the procedure for the demonstration
到目前为止,这实际上效果很好。
所以在我的问题中,我觉得我已经确定了一些基本情况,带有退出子句的线程,没有退出子句的线程,以及无法恢复的线程,或者一次射击(本质上只是一个函数调用,但我想保持一致,因此它必须在 "thread" 而不仅仅是函数调用中)
(let ((spawn-thread
(lambda (it . args)
(call/cc (apply it args))))
(main
(lambda (label reps . sequence)
;for consistency, main is also a thread, but does not need to be
;this will take a number of repetitions, and a sequence of continuations
;to call, pushing the continuation returned from the top continuation in
;sequence to the end, and then calling the loop again
(lambda (cc)
(let loop ((sequence sequence) (state 0))
(printf "IN MAIN THREAD STATE: ~A~N---" state)
(if (< state reps) ;this is essentially a queue but without assignment
(loop `(,@(cdr sequence) ,(call/cc (car sequence)))
(+ state 1)))))))
(with-exit
(lambda (label data)
;thread with exit case
(lambda (cc)
(let loop ((cc cc) (done (lambda () #f)) (state 0))
(cond ((done) (cc data)) ;if done was replaced with something else that
;could at some point return true, this is where
;the thread would exit
(else
(printf "IN THREAD ~A TYPE: WITH-EXIT STATE: ~A~N" label state)
(loop (call/cc cc) done (+ state 1))))))))
(no-exit
(lambda (label data)
;no exit case, can be resumed arbitrarily
(lambda (cc)
(let loop ((cc cc) (state 0))
(printf "IN THREAD ~A TYPE: NO-EXIT STATE: ~A~N" label state)
(loop (call/cc cc) (+ state 1))))))
(no-reps
(lambda (label data)
;breaks it for some reason?
;would be called, do its stuff and then
;go back to the calling continuation
(lambda (cc)
(printf "IN THREAD ~A TYPE: NO-REPS~N" label)
(call/cc cc)))))
(spawn-thread main 'main 10
(spawn-thread with-exit 1 '())
(spawn-thread no-exit 2 '())
(spawn-thread with-exit 3 '())
;(spawn-thread no-reps 4 '())) uncomment to see error
))
那么没有重复是怎么回事?为什么 运行 它作为 main 中的线程之一会导致无限循环?
带有注释行的示例输出:
IN THREAD 1 TYPE: WITH-EXIT STATE: 0
IN THREAD 2 TYPE: NO-EXIT STATE: 0
IN THREAD 3 TYPE: WITH-EXIT STATE: 0
IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 1
---IN THREAD 2 TYPE: NO-EXIT STATE: 1
IN MAIN THREAD STATE: 2
---IN THREAD 3 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 3
---IN THREAD 1 TYPE: WITH-EXIT STATE: 2
IN MAIN THREAD STATE: 4
---IN THREAD 2 TYPE: NO-EXIT STATE: 2
IN MAIN THREAD STATE: 5
---IN THREAD 3 TYPE: WITH-EXIT STATE: 2
IN MAIN THREAD STATE: 6
---IN THREAD 1 TYPE: WITH-EXIT STATE: 3
IN MAIN THREAD STATE: 7
---IN THREAD 2 TYPE: NO-EXIT STATE: 3
IN MAIN THREAD STATE: 8
---IN THREAD 3 TYPE: WITH-EXIT STATE: 3
IN MAIN THREAD STATE: 9
---IN THREAD 1 TYPE: WITH-EXIT STATE: 4
IN MAIN THREAD STATE: 10
未评论:
IN THREAD 1 TYPE: WITH-EXIT STATE: 0
IN THREAD 2 TYPE: NO-EXIT STATE: 0
IN THREAD 3 TYPE: WITH-EXIT STATE: 0
IN THREAD 4 TYPE: NO-REPS
IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 1
---IN THREAD 2 TYPE: NO-EXIT STATE: 1
IN MAIN THREAD STATE: 2
---IN THREAD 3 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
......... ;profit????
不确定您使用的是哪个实现,但我无法通过取消注释表达式来获得无限循环。 (我使用了几个 R6RS 实现,包括 Racket。)
为了让事情更简单,我已经剥离了你的代码:
#!r6rs
(import (rnrs))
(define (print . args) (for-each display args) (newline))
(let ((spawn-thread
(lambda (it . args)
(call/cc (apply it args))))
(main
(lambda (label reps . sequence)
(lambda (cc)
(print sequence)
(let loop ((sequence sequence) (state 0))
(print "IN MAIN THREAD STATE: " state)
(display "---")
(if (< state reps)
(let ((next `(,@(cdr sequence) ,(call/cc (car sequence))) ))
(loop next (+ state 1))))))))
(no-reps
(lambda (label data)
(lambda (cc)
(print "IN THREAD "label" TYPE: NO-REPS")
(call/cc cc)))))
(spawn-thread main 'main 10
;; *1
(spawn-thread no-reps 4 '())))
重点是*1
的返回延续。过程 spawn-thread
执行 no-reps
过程,并且 no-reps
returns 下一个进程调用 main 的 spawn-thread
的给定延续。因此,no-reps
在此上下文中实际做的是复制主线程。下面的执行结果,运行 on Racket,显示出来:
IN THREAD 4 TYPE: NO-REPS
{#<continuation>}
IN MAIN THREAD STATE: 0
---{#<continuation>}
IN MAIN THREAD STATE: 0
---IN MAIN THREAD STATE: 1
---IN MAIN THREAD STATE: 1
---IN MAIN THREAD STATE: 2
---IN MAIN THREAD STATE: 2
---IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 4
---IN MAIN THREAD STATE: 4
---IN MAIN THREAD STATE: 5
---IN MAIN THREAD STATE: 5
---IN MAIN THREAD STATE: 6
---IN MAIN THREAD STATE: 6
---IN MAIN THREAD STATE: 7
---IN MAIN THREAD STATE: 7
---IN MAIN THREAD STATE: 8
---IN MAIN THREAD STATE: 8
---IN MAIN THREAD STATE: 9
---IN MAIN THREAD STATE: 9
---IN MAIN THREAD STATE: 10
---%
作为序言,我喜欢自己滚动,这是一个以学习为目的的练习,但我最终想从这个练习中获取信息,并在此处实现一些封装行为的宏。这就是为什么我使用了很多 let
因为还没有最终确定并且定义太 "heavy".
所以你可以使用call/cc来实现各种不同的协作线程结构,我使用的线程模型通常是:
(let ((generic-thread
(lambda (cc)
(let loop ((cc cc))
(printf "doing stuff~N")
(loop (call/cc cc)))))) ;this is the magic, it calls the calling continuation
(let loop ((its 0) ;and then loops with the result of that
(cc generic-thread)) ;so when its resumed, it still has its new state
(if (< its 10)
(loop (+ its 1) (call/cc cc))))) ;just repeats the procedure for the demonstration
到目前为止,这实际上效果很好。
所以在我的问题中,我觉得我已经确定了一些基本情况,带有退出子句的线程,没有退出子句的线程,以及无法恢复的线程,或者一次射击(本质上只是一个函数调用,但我想保持一致,因此它必须在 "thread" 而不仅仅是函数调用中)
(let ((spawn-thread
(lambda (it . args)
(call/cc (apply it args))))
(main
(lambda (label reps . sequence)
;for consistency, main is also a thread, but does not need to be
;this will take a number of repetitions, and a sequence of continuations
;to call, pushing the continuation returned from the top continuation in
;sequence to the end, and then calling the loop again
(lambda (cc)
(let loop ((sequence sequence) (state 0))
(printf "IN MAIN THREAD STATE: ~A~N---" state)
(if (< state reps) ;this is essentially a queue but without assignment
(loop `(,@(cdr sequence) ,(call/cc (car sequence)))
(+ state 1)))))))
(with-exit
(lambda (label data)
;thread with exit case
(lambda (cc)
(let loop ((cc cc) (done (lambda () #f)) (state 0))
(cond ((done) (cc data)) ;if done was replaced with something else that
;could at some point return true, this is where
;the thread would exit
(else
(printf "IN THREAD ~A TYPE: WITH-EXIT STATE: ~A~N" label state)
(loop (call/cc cc) done (+ state 1))))))))
(no-exit
(lambda (label data)
;no exit case, can be resumed arbitrarily
(lambda (cc)
(let loop ((cc cc) (state 0))
(printf "IN THREAD ~A TYPE: NO-EXIT STATE: ~A~N" label state)
(loop (call/cc cc) (+ state 1))))))
(no-reps
(lambda (label data)
;breaks it for some reason?
;would be called, do its stuff and then
;go back to the calling continuation
(lambda (cc)
(printf "IN THREAD ~A TYPE: NO-REPS~N" label)
(call/cc cc)))))
(spawn-thread main 'main 10
(spawn-thread with-exit 1 '())
(spawn-thread no-exit 2 '())
(spawn-thread with-exit 3 '())
;(spawn-thread no-reps 4 '())) uncomment to see error
))
那么没有重复是怎么回事?为什么 运行 它作为 main 中的线程之一会导致无限循环?
带有注释行的示例输出:
IN THREAD 1 TYPE: WITH-EXIT STATE: 0
IN THREAD 2 TYPE: NO-EXIT STATE: 0
IN THREAD 3 TYPE: WITH-EXIT STATE: 0
IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 1
---IN THREAD 2 TYPE: NO-EXIT STATE: 1
IN MAIN THREAD STATE: 2
---IN THREAD 3 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 3
---IN THREAD 1 TYPE: WITH-EXIT STATE: 2
IN MAIN THREAD STATE: 4
---IN THREAD 2 TYPE: NO-EXIT STATE: 2
IN MAIN THREAD STATE: 5
---IN THREAD 3 TYPE: WITH-EXIT STATE: 2
IN MAIN THREAD STATE: 6
---IN THREAD 1 TYPE: WITH-EXIT STATE: 3
IN MAIN THREAD STATE: 7
---IN THREAD 2 TYPE: NO-EXIT STATE: 3
IN MAIN THREAD STATE: 8
---IN THREAD 3 TYPE: WITH-EXIT STATE: 3
IN MAIN THREAD STATE: 9
---IN THREAD 1 TYPE: WITH-EXIT STATE: 4
IN MAIN THREAD STATE: 10
未评论:
IN THREAD 1 TYPE: WITH-EXIT STATE: 0
IN THREAD 2 TYPE: NO-EXIT STATE: 0
IN THREAD 3 TYPE: WITH-EXIT STATE: 0
IN THREAD 4 TYPE: NO-REPS
IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 1
---IN THREAD 2 TYPE: NO-EXIT STATE: 1
IN MAIN THREAD STATE: 2
---IN THREAD 3 TYPE: WITH-EXIT STATE: 1
IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 0
---IN THREAD 1 TYPE: WITH-EXIT STATE: 1
......... ;profit????
不确定您使用的是哪个实现,但我无法通过取消注释表达式来获得无限循环。 (我使用了几个 R6RS 实现,包括 Racket。)
为了让事情更简单,我已经剥离了你的代码:
#!r6rs
(import (rnrs))
(define (print . args) (for-each display args) (newline))
(let ((spawn-thread
(lambda (it . args)
(call/cc (apply it args))))
(main
(lambda (label reps . sequence)
(lambda (cc)
(print sequence)
(let loop ((sequence sequence) (state 0))
(print "IN MAIN THREAD STATE: " state)
(display "---")
(if (< state reps)
(let ((next `(,@(cdr sequence) ,(call/cc (car sequence))) ))
(loop next (+ state 1))))))))
(no-reps
(lambda (label data)
(lambda (cc)
(print "IN THREAD "label" TYPE: NO-REPS")
(call/cc cc)))))
(spawn-thread main 'main 10
;; *1
(spawn-thread no-reps 4 '())))
重点是*1
的返回延续。过程 spawn-thread
执行 no-reps
过程,并且 no-reps
returns 下一个进程调用 main 的 spawn-thread
的给定延续。因此,no-reps
在此上下文中实际做的是复制主线程。下面的执行结果,运行 on Racket,显示出来:
IN THREAD 4 TYPE: NO-REPS
{#<continuation>}
IN MAIN THREAD STATE: 0
---{#<continuation>}
IN MAIN THREAD STATE: 0
---IN MAIN THREAD STATE: 1
---IN MAIN THREAD STATE: 1
---IN MAIN THREAD STATE: 2
---IN MAIN THREAD STATE: 2
---IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 3
---IN MAIN THREAD STATE: 4
---IN MAIN THREAD STATE: 4
---IN MAIN THREAD STATE: 5
---IN MAIN THREAD STATE: 5
---IN MAIN THREAD STATE: 6
---IN MAIN THREAD STATE: 6
---IN MAIN THREAD STATE: 7
---IN MAIN THREAD STATE: 7
---IN MAIN THREAD STATE: 8
---IN MAIN THREAD STATE: 8
---IN MAIN THREAD STATE: 9
---IN MAIN THREAD STATE: 9
---IN MAIN THREAD STATE: 10
---%