协作线程,无分配



作为序言,我喜欢自己滚动,这是一个用于学习目的的练习,但我想最终从这个练习中获取信息,并实现一些封装这里行为的宏。这就是为什么我使用了很多let,因为还没有最终确定,定义太"重"。

所以你可以使用 call/cc 来实现各种不同的协作线程构造,im 使用的线程的模型一般是:

(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

到目前为止,这实际上效果很好。

所以

在我的问题中,我觉得我确定了几个基本情况,带有退出子句的线程,没有它们的线程,以及无法恢复的线程,或者一次性(本质上只是一个函数调用,但我想保持一致,所以它必须在"线程"中,而不仅仅是函数调用)

(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返回给定的延续,其下一个进程调用 main spawn-thread。因此,no-reps在此上下文中实际执行的操作是复制主线程。以下在 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
---%

最新更新