I have a (possibly irrational) bias against mutexes, and attempted to solve a threading problem with just message passing. The code works, but only part of the time.
This code:
(let ((th (thread-start! (make-thread (lambda () (let lp () (let ((p (thread-receive 0 #f))) (if p (p 40) (begin (thread-yield!) (lp)))))))))) (+ 2 (call/cc (lambda (ret) (thread-send th ret) (thread-sleep! 4)))))
Occasionally fails by attempting to add 2 to #!void. Actually, it raises the error, but returns 42 anyway. Seems like I can get away with 4 or 5 evaluations before I hit the failure condition. It seems risky, but I was wondering if someone could explain why? If I increase thread-receive's timeout to 1, it succeeds consistently, but I haven't tried it with lots of threads -- I assume it's a race condition that would reappear.
Where is the #!void coming from? Is the execution of the continuation interrupting the thread-sleep!, but returning the value of the sleep rather than the value passed to the continuation? I'm willing to use mutexes, but I'm curious.
Incidentally, the end goal is a stack of database connections, maintained through mutation. It's intended to be thread-safe, so I was planning on closing over a designated thread to do the mutations, and having it return values to the calling functions through this mechanism. I'll use mutexes if that's the right solution.
Lang