chickadee » srfi-18 » thread-terminate!

thread-terminate! threadprocedure

Causes an abnormal termination of the thread. If the thread is not already terminated, all mutexes owned by the thread become unlocked/abandoned and a "terminated thread exception" object is stored in the thread's end-exception field. If thread is the current thread, thread-terminate! does not return. Otherwise thread-terminate! returns an unspecified value; the termination of the thread will occur before thread-terminate! returns.

    (thread-terminate! (current-thread))  ==>  ''does not return''
 
    (define (amb thunk1 thunk2)
      (let ((result #f)
            (result-mutex (make-mutex))
            (done-mutex (make-mutex)))
        (letrec ((child1
                  (make-thread
                    (lambda ()
                      (let ((x (thunk1)))
                        (mutex-lock! result-mutex #f #f)
                        (set! result x)
                        (thread-terminate! child2)
                        (mutex-unlock! done-mutex)))))
                 (child2
                  (make-thread
                    (lambda ()
                      (let ((x (thunk2)))
                        (mutex-lock! result-mutex #f #f)
                        (set! result x)
                        (thread-terminate! child1)
                        (mutex-unlock! done-mutex))))))
          (mutex-lock! done-mutex #f #f)
          (thread-start! child1)
          (thread-start! child2)
          (mutex-lock! done-mutex #f #f)
          result)))

NOTE: This operation must be used carefully because it terminates a thread abruptly and it is impossible for that thread to perform any kind of cleanup. This may be a problem if the thread is in the middle of a critical section where some structure has been put in an inconsistent state. However, another thread attempting to enter this critical section will raise an "abandoned mutex exception" because the mutex is unlocked/abandoned. This helps avoid observing an inconsistent state. Clean termination can be obtained by polling, as shown in the example below.

    (define (spawn thunk)
      (let ((t (make-thread thunk)))
        (thread-specific-set! t #t)
        (thread-start! t)
        t))
 
    (define (stop! thread)
      (thread-specific-set! thread #f)
      (thread-join! thread))
 
    (define (keep-going?)
      (thread-specific (current-thread)))
 
    (define count!
      (let ((m (make-mutex))
            (i 0))
        (lambda ()
          (mutex-lock! m)
          (let ((x (+ i 1)))
            (set! i x)
            (mutex-unlock! m)
            x))))
 
    (define (increment-forever!)
      (let loop () (count!) (if (keep-going?) (loop))))
 
    (let ((t1 (spawn increment-forever!))
          (t2 (spawn increment-forever!)))
      (thread-sleep! 1)
      (stop! t1)
      (stop! t2)
      (count!))  ==>  377290