STklos Reference Manual
9. Threads, Mutexes and Condition Variables


Contents

The thread system provides the following data types:

  • Thread (a virtual processor which shares object space with all other threads)
  • Mutex (a mutual exclusion device, also known as a lock and binary semaphore)
  • Condition variable (a set of blocked threads)

The STklos thread system is conform to SRFI-18 (Multithreading support), and implement all the SRFI mechanisms. See this SRFI documentation for a more complete description

9.1 Threads


(make-thread thunk)STklos procedure
(make-thread thunk name)
(make-thread thunk name stack-size)

Returns a new thread. This thread is not automatically made runnable (the procedure thread-start! must be used for this). A thread has the following fields: name, specific, end-result, end-exception, and a list of locked/owned mutexes it owns. The thread's execution consists of a call to thunk with the "initial continuation". This continuation causes the (then) current thread to store the result in its end-result field, abandon all mutexes it owns, and finally terminate. The dynamic-wind stack of the initial continuation is empty. The optional name is an arbitrary Scheme object which identifies the thread (useful for debugging); it defaults to an unspecified value. The specific field is set to an unspecified value. The thread inherits the dynamic environment from the current thread. Moreover, in this dynamic environment the exception handler is bound to the "initial exception handler" which is a unary procedure which causes the (then) current thread to store in its end-exception field an "uncaught exception" object whose "reason" is the argument of the handler, abandon all mutexes it owns, and finally terminate.

Note: The optional parameter stack-size permits to specify the size (in words) reserved for the thread. This option does not exist in SRFI-18.

(current-thread)STklos procedure

Returns the current thread.
(eq? (current-thread) (current-thread))  ⇒  #t

(thread-start! thread)STklos procedure

Makes thread runnable. The thread must be a new thread. Thread-start! returns the thread.
(let ((t (thread-start! (make-thread
                           (lambda () (write 'a))))))
   (write 'b)
   (thread-join! t))       ⇒  unspecified
                               after writing ab or ba

(thread-yield!)STklos procedure

The current thread exits the running state as if its quantum had expired. Thread-yield! returns an unspecified value.

(thread-terminate! thread)STklos procedure

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.

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.

(thread-sleep! timeout)STklos procedure

The current thread waits until the timeout is reached. This blocks the thread only if timeout represents a point in the future. It is an error for timeout to be #f. Thread-sleep! returns an unspecified value.

(thread-join! thread)STklos procedure
(thread-join! thread timeout)
(thread-join! thread timeout timeout-val)

The current thread waits until the thread terminates (normally or not) or until the timeout is reached if timeout is supplied. If the timeout is reached, thread-join! returns timeout-val if it is supplied, otherwise a "join timeout exception" is raised. If the thread terminated normally, the content of the end-result field is returned, otherwise the content of the end-exception field is raised.
(let ((t (thread-start! (make-thread (lambda ()
                                       (expt 2 100))))))
  (thread-sleep! 1)
  (thread-join! t)) ⇒ 1267650600228229401496703205376

(thread? obj)STklos procedure

Returns #t if obj is a thread, otherwise returns #f.
(thread? (current-thread))  ⇒ #t
(thread? 'foo)              ⇒ #f

(thread-name thread)STklos procedure

Returns the name of the thread.
(thread-name (make-thread (lambda () #f) 'foo))  ⇒  foo

(thread-stack-size thread)STklos procedure

Returns the allocated stack size for thread. Note that this procedure is not present in SRFI-18.

(thread-specific thread)STklos procedure

Returns the content of the thread's specific field.

(thread-specific-set! thread)STklos procedure

Stores obj into the thread's specific field. Thread-specific-set! returns an unspecified value.
(thread-specific-set! (current-thread) "hello")
           ⇒  unspecified
(thread-specific (current-thread))
           ⇒  "hello"

9.2 Mutexes


(make-mutex)STklos procedure
(make-mutex name)

Returns a new mutex in the unlocked/not-abandoned state. The optional name is an arbitrary Scheme object which identifies the mutex (useful for debugging); it defaults to an unspecified value. The mutex's specific field is set to an unspecified value.

(mutex? obj)STklos procedure

Returns #t if obj is a mutex, otherwise returns #f.

(mutex-name mutex)STklos procedure

Returns the name of the mutex.
(mutex-name (make-mutex 'foo))  ⇒  foo

(mutex-specific mutex)STklos procedure

Returns the content of the mutex's specific field.

(mutex-specific! mutex obj)STklos procedure

Stores obj into the mutex's specific field and eturns an unspecified value.
(define m (make-mutex))
(mutex-specific-set! m "hello")  ⇒  unspecified
(mutex-specific m)               ⇒  "hello"

(define (mutex-lock-recursively! mutex)
  (if (eq? (mutex-state mutex) (current-thread))
      (let ((n (mutex-specific mutex)))
        (mutex-specific-set! mutex (+ n 1)))
      (begin
        (mutex-lock! mutex)
        (mutex-specific-set! mutex 0))))

(define (mutex-unlock-recursively! mutex)
  (let ((n (mutex-specific mutex)))
    (if (= n 0)
        (mutex-unlock! mutex)
        (mutex-specific-set! mutex (- n 1)))))

(mutex-state mutex)STklos procedure

Returns information about the state of the mutex. The possible results are:
  • thread T: the mutex is in the locked/owned state and thread T is the owner of the mutex
  • symbol not-owned: the mutex is in the locked/not-owned state
  • symbol abandoned: the mutex is in the unlocked/abandoned state
  • symbol not-abandoned: the mutex is in the unlocked/not-abandoned state
(mutex-state (make-mutex))  ⇒  not-abandoned

(define (thread-alive? thread)
  (let ((mutex (make-mutex)))
    (mutex-lock! mutex #f thread)
    (let ((state (mutex-state mutex)))
      (mutex-unlock! mutex) ; avoid space leak
      (eq? state thread))))

(mutex-lock! mutex)STklos procedure
(mutex-lock! mutex timeout)
(mutex-lock! mutex timeout thread)

If the mutex is currently locked, the current thread waits until the mutex is unlocked, or until the timeout is reached if timeout is supplied. If the timeout is reached, mutex-lock! returns #f. Otherwise, the state of the mutex is changed as follows:
  • if thread is #f the mutex becomes locked/not-owned,
  • otherwise, let T be thread (or the current thread if thread is not supplied),
    • if T is terminated the mutex becomes unlocked/abandoned,
    • otherwise mutex becomes locked/owned with T as the owner.


After changing the state of the mutex, an "abandoned mutex exception" is raised if the mutex was unlocked/abandoned before the state change, otherwise mutex-lock! returns #t.
(define (sleep! timeout)
  ;; an alternate implementation of thread-sleep!
  (let ((m (make-mutex)))
  (mutex-lock! m #f #f)
  (mutex-lock! m timeout #f)))

(mutex-unlock! mutex)STklos procedure
(mutex-unlock! mutex condition-variable)
(mutex-unlock! mutex condition-variable timeout)

Unlocks the mutex by making it unlocked/not-abandoned. It is not an error to unlock an unlocked mutex and a mutex that is owned by any thread. If condition-variable is supplied, the current thread is blocked and added to the condition-variable before unlocking mutex; the thread can unblock at any time but no later than when an appropriate call to condition-variable-signal! or condition-variable-broadcast! is performed (see below), and no later than the timeout (if timeout is supplied). If there are threads waiting to lock this mutex, the scheduler selects a thread, the mutex becomes locked/owned or locked/not-owned, and the thread is unblocked. mutex-unlock! returns #f when the timeout is reached, otherwise it returns #t.

9.3 Condition Variables


(make-conditon-variable)STklos procedure
(make-conditon-variable name)

Returns a new empty condition variable. The optional name is an arbitrary Scheme object which identifies the condition variable (useful for debugging); it defaults to an unspecified value. The condition variable's specific field is set to an unspecified value.

(conditon-variable? obj)STklos procedure

Returns #t if obj is a condition variable, otherwise returns #f.

(conditon-variable-name conditon-variable)STklos procedure

eturns the name of the condition-variable.

(conditon-variable-specific conditon-variable)STklos procedure

Returns the content of the condition-variable's specific field.

(conditon-variable-specific-set! conditon-variable obj)STklos procedure

Stores obj into the condition-variable's specific field.

(condition-variable-signal! condition-variable)STklos procedure

If there are threads blocked on the condition-variable, the scheduler selects a thread and unblocks it. Condition-variable-signal! returns an unspecified value.

(condition-variable-broadcast! condition-variable)STklos procedure

Unblocks all the threads blocked on the condition-variable. Condition-variable-broadcast! returns an unspecified value.

9.4 Conditions


(join-timeout-exception? obj)STklos procedure

Returns #t if obj is a "join timeout exception" object, otherwise returns #f. A join timeout exception is raised when thread-join! is called, the timeout is reached and no timeout-val is supplied.

(abandoned-mutex-exception? obj)STklos procedure

Returns #t if obj is an "abandoned mutex exception" object, otherwise returns #f. An abandoned mutex exception is raised when the current thread locks a mutex that was owned by a thread which terminated (see mutex-lock!).

(terminated-thread-exception? obj)STklos procedure

Returns #t if obj is a "terminated thread exception" object, otherwise returns #f. A terminated thread exception is raised when thread-join! is called and the target thread has terminated as a result of a call to thread-terminate!.

(uncaught-exception? obj)STklos procedure

Returns #t if obj is an "uncaught exception" object, otherwise returns #f. An uncaught exception is raised when thread-join! is called and the target thread has terminated because it raised an exception that called the initial exception handler of that thread.

(uncaught-exception-reason exc)STklos procedure

Returns the object which was passed to the initial exception handler of that thread (exc must be an "uncaught exception" object).

This Html page has been produced by Skribe.
Last update Sat Dec 31 15:49:34 2011