(define p (make-parameter #f))
(define t (make-thread-cell #f))
(define k #f)
(parameterize ((p 'thread-one))
(thread-cell-set! t 'thread-one)
(display "In thread 1:")
(let/cc my-k (set! k my-k))
(printf "param: ~a, tc: ~a\n" (p) (thread-cell-ref t)))))
(parameterize ((p 'thread-two))
(thread-cell-set! t 'thread-two)
(display "In thread 2, throwing to a continuation created by
This prints out:
In thread 1:
param: thread-one, tc: thread-one
In thread 2, throwing to a continuation created by thread 1:
param: thread-one, tc: thread-two
The second half of the printout is the interesting part. It shows that a continuation stores the parameter settings in effect when it is captured and carries them to new threads; it does not, on the other hand, capture the current values of thread-cells. This makes thread-cells, despite their obscurity, the better choice for implementing a lot of things; for instance, in an OS-like program that uses continuations to represent user processes and threads to represent particular slices of computation, thread-cells are the right abstraction for holding onto the OS resources that are particular to a thread.
That example wasn't pulled out of thin air, of course. It's actually how I came to learn about thread-cells at all, in fact; the PLT web server had an odd bug that cropped up because some resources that should be thread-cells were parameters instead, the result of which was that servlets that tried to save continuation objects occasionally found that when they eventually threw to them the servlet would die abruptly.
This is now fixed, and to celebrate I released a somewhat nifty new PLaneT package that highlights the power of being able to write abstractions over web interaction patterns rather than just web pages: resume.plt.