(asdf:oos 'asdf:load-op 'bordeaux-threads)

(defpackage :btt (:use :cl))

(in-package :btt)

(defun thread-body (stream cond-var lock-var)
  (format stream "WAITING... (~S)~%" (bt:current-thread))
  (bt:condition-wait cond-var lock-var)
  (format stream "NOTIFIED!  (~S)~%" (bt:current-thread)))

(defun test-condition-variables (n-threads)
  (let* ((cond-var (bt:make-condition-variable))
         (lock-var (bt:make-lock))
         (stream *trace-output*)
         (threads
          (loop repeat n-threads
                collect (bt:make-thread
                         (lambda () (thread-body stream cond-var lock-var))))))
    (sleep 10.0)
; The assertion (EQ SB-THREAD::ME
;                   (SB-THREAD::MUTEX-%OWNER SB-THREAD:MUTEX)) failed.
;    [Condition of type SIMPLE-ERROR]
; 
; Restarts:
;  0: [CONTINUE] Retry assertion.
;  1: [TERMINATE-THREAD] Terminate this thread (#<THREAD "Anonymous" RUNNING {10027AAE21}>)
; 
; Backtrace:
;   0: (SB-KERNEL:ASSERT-ERROR (EQ SB-THREAD::ME (SB-THREAD::MUTEX-%OWNER SB-THREAD:MUTEX)) NIL NIL)[:EXTERNAL]
;   1: (SB-THREAD:CONDITION-WAIT #S(SB-THREAD:WAITQUEUE :NAME NIL :DATA NIL) #S(SB-THREAD:MUTEX :NAME NIL :%OWNER NIL :STATE 0))
;   2: (SB-THREAD:CONDITION-WAIT #S(SB-THREAD:WAITQUEUE :NAME NIL :DATA NIL) #S(SB-THREAD:MUTEX :NAME NIL :%OWNER NIL :STATE 0))[:EXTERNAL]
;   3: (BTT::THREAD-BODY #<SWANK-BACKEND::SLIME-OUTPUT-STREAM {1002ACA601}> #S(SB-THREAD:WAITQUEUE :NAME NIL :DATA NIL) #S(SB-THREAD:MUTEX :NAME NIL :%OWNER NIL :STATE 0))
;   4: ((LAMBDA ()))
;   5: ((FLET SB-THREAD::WITH-MUTEX-THUNK))
;   6: ((FLET #:WITHOUT-INTERRUPTS-BODY-[CALL-WITH-MUTEX]478))
;   7: (SB-THREAD::CALL-WITH-MUTEX ..)
;   8: ((LAMBDA ()))
;   9: ("foreign function: #x41F1B2")
;  10: ("foreign function: #x4165CA")
;  --more--
    (format stream "Notifying...~%")
    (bt:condition-notify cond-var)
    (dolist (thread threads)
      (format stream "~:[Active Thread: ~S~;Inactive Thread: ~S~]~%"
              (bt:thread-alive-p thread) thread)
      (when (bt:thread-alive-p thread)
        (bt:destroy-thread thread)))
    (format stream "Exiting...~%")))
