17. Bigloo
A ``practical Scheme compiler''
User manual for version 3.2a
January 2009 -- Threads
Bigloo supports multithreaded programming. Two different libraries programming are available. The first one, the Fair Thread (see Section Fair Threads), enables, simple, easy to develop and to maintain code. The second one, the Posix Thread (see Section Posix Threads) enables more easily to take benefit of the actual parallelism that is now available on stock hardware. Because it is easier to program with fthread than with pthread, we strongly recommend to use the former as much as possible and leave the former for specially demanding applications. Both libraries are described in this chapter.

17.1 Thread Common Functions

This section describes the functions that are available independently of the multi-threading library.

mutex? objSRFI-18 function
make-mutex [name]SRFI-18 function
mutex-name mutexSRFI-18 function
mutex-specific mutexSRFI-18 function
mutex-specific-set! mutex objSRFI-18 function
mutex-state mutexSRFI-18 function
mutex-lock! mutex [timeout [thread]]SRFI-18 function
mutex-unlock! mutexSRFI-18 function
(let ((m (make-mutex)))
   (thread-start!
    (make-thread (lambda ()
                    (let loop ()
                       (if (mutex-lock! m 0)
                           (begin
                              (display "locked")
                              (mutex-unlock! m))
                           (begin
                              (thread-yield!)
                              (loop))))))))
  -| locked

(let ((res '())) (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))))) (thread-start! (make-thread (lambda () (let ((m (make-mutex))) (mutex-lock-recursively! m) (mutex-lock-recursively! m) (mutex-lock-recursively! m) (set! res (cons (mutex-specific m) res)) (mutex-unlock-recursively! m) (mutex-unlock-recursively! m) (mutex-unlock-recursively! m) (set! res (cons (mutex-specific m) res)))))) res) => (0 2)

with-lock mutex thunkBigloo function
The function with-lock evaluates the body of the thunk. The mutex mutex is acquired and released before thunk gets invoked. The function with-lock might be implemented as:

(define (with-lock mutex thunk)
   (mutex-lock! mutex)
   (unwind-protect
      (thunk)
      (mutex-unlock! mutex)))

condition-variable? objSRFI-18 function
make-condition-variable [name]SRFI-18 function
condition-variable-name cvSRFI-18 function
condition-variable-specific cvSRFI-18 function
condition-variable-specific-set! cv objSRFI-18 function
condition-variable-wait! cv mutexSRFI-18 function
condition-variable-signal! cvSRFI-18 function
condition-variable-broadcast! cvSRFI-18 function
(let ((res 0))
   (define (make-semaphore n)
      (vector n (make-mutex) (make-condition-variable)))
   (define (semaphore-wait! sema)
      (mutex-lock! (vector-ref sema 1))
      (let ((n (vector-ref sema 0)))
         (if (> n 0)
             (begin
                (vector-set! sema 0 (- n 1))
                (mutex-unlock! (vector-ref sema 1)))
             (begin
                (mutex-unlock! (vector-ref sema 1) (vector-ref sema 2))
                (semaphore-wait! sema)))))
   (define (semaphore-signal-by! sema increment)
      (mutex-lock! (vector-ref sema 1))
      (let ((n (+ (vector-ref sema 0) increment)))
         (vector-set! sema 0 n)
         (if (> n 0)
             (condition-variable-broadcast! (vector-ref sema 2)))
         (mutex-unlock! (vector-ref sema 1))))
   (let ((sema (make-semaphore 10)))
      (let ((t1 (thread-start! (make-thread
                                (lambda ()
                                   (semaphore-wait! sema)
                                   (set! res (current-time))))))
            (t2 (thread-start! (make-thread
                                (lambda ()
                                   (let loop ((n 10))
                                      (if (> n 0)
                                          (begin
                                             (semaphore-signal-by! sema 1)
                                             (thread-yield!)
                                             (loop (- n 1))))))))))
         (scheduler-start!)
         res)))
  => 2

thread-parameter identBigloo function
Returns the value of the parameter ident in the current thread. If no value is bound to this parameter, #f is returned.

A thread parameter is implemented by a chunk of memory specific to each thread. All threads are created with an empty set of parameters.

thread-parameter-set! ident valueBigloo function
Associates a value to a parameter named ident.


17.2 Threads

Bigloo supports fair threads (see Section Thread), a specification of cooperative threads. In this framework a thread must explicitly or implicitly yield the processor to the scheduler (see Section Scheduler). Explicit cooperation is achieved by library functions such as thread-yield! or thread-sleep!. The scheduler does not preempt a running thread to allocate the processor to another waiting thread. Fair threads have two drawbacks over preemptive threads:

  • Cooperative threads are not skilled to benefit of multi processors platforms.
  • Single threads programs must be adapted in order to be ran concurrently.
On the other hand, Fair threads have advantages that make them suitable for a high level programming language such as Scheme:

  • Fair threads have a strong and well defined semantic. Multi threaded programs using Fair threads are deterministic thus programs that deploy Fair threads are predictable.
  • Fair threads are easier to program with because they hide most the of the concurrent programming pitfalls. In particular, since Fair threads enforce a strong synchronization, there is no need to deploy techniques such as mutex, semaphore or condition variables.
This whole chapter has been written in collaboration with Frédéric Boussinot. It uses materials on Fair threads that can be found at http://www-sop.inria.fr/mimosa/rp/FairThreads/html/FairThreads.html.

17.2.1 Introduction to Fair Threads

Fair threads are cooperative threads run by a fair scheduler which gives them equal access to the processor. Fair threads can communicate using broadcast events. Their semantics does not depends on the executing platform. Fine control over fair threads execution is possible allowing the programming of specific user-defined scheduling strategies.

Contrary to standard sequential programming where the processor executes a single program, in concurrent programming the processor is a shared resource which is dispatched to several programs. The term concurrent is appropriate because programs can be seen as concurrently competing to gain access to the processor, in order to execute.

Threads are a basic mean for concurrent programming, and are widely used in operating systems. At language level, threads offer a way to structure programs by decomposing systems in several concurrent components; in this respect, threads are useful for modularity.

However, threads are generally considered as low-level primitives leading to over-complex programming. Moreover, threads generally have loose semantics, in particular depending on the underlying executing platform; to give them a precise semantics is a difficult task, and this is a clearly identified problem to get portable code.

Bigloo proposes a new framework with clear and simple semantics, and with an efficient implementation. In it, threads are called fair; basically a fair thread is a cooperative thread executed in a context in which all threads always have equal access to the processor. Fair threads have a deterministic semantics, relying on previous work belonging to the so-called reactive approach.

17.2.2 Fair Threads Api

Bigloo uses a set of primitive functions to create, run and handle thread. For the sake of standardization the name and semantic of SRFI-18 (Multithreading support) has been used. This section presents only the mandatory functions to program with Fair threads in Bigloo. The Section SRFI-18 presents the functions that are not necessary to Bigloo but supported for compliance with SRFI-18.

17.2.2.1 Thread

current-threadSRFI-18 function
Returns the current thread.

thread? objSRFI-18 function
Returns #t if obj is a thread, otherwise returns #f.

make-thread thunk [name]SRFI-18 function
Returns a new thread which is not started yet. The body of the thread is the body of the procedure thunk. The optional argument name can be use to identify the thread. It can be any Bigloo value.

(make-thread (lambda () (print 1) (thread-yield!) (print 2)) 'my-thread)

thread-start! thread [scheduler]SRFI-18 function
Runs a thread created with make-thread. If scheduler is provided, the thread is started this particular scheduler. Otherwise, it is started in the current scheduler (see Section Scheduler). Threads are started at the beginning of reactions (see Section Scheduler).

thread-name threadSRFI-18 function
Returns the name of the thread that has been passed to make-thread.

thread-specific threadSRFI-18 function
thread-specific-set! thread objSRFI-18 function
Returns and sets value in the specific field of the thread. If no value has been set, thread-specific returns an unspecified value.

(let ((t (make-thread (lambda () 
                         (print (thread-specific (current-thread)))))))
   (thread-specific-set! t 'foo)
   (thread-start! t)) -| foo

thread-cleanup threadBigloo function
thread-cleanup-set! thread funBigloo function
Associates a cleanup function to a thread. The cleanup function is called with the thread itself. The cleanup function is executed in a context where current-thread is the thread owning the cleanup function.

(let ((t (make-thread (lambda () 'done) 'foo)))
   (thread-cleanup-set! t (lambda (v) (print (thread-name (current-thread))
					     ", exit value: " v)))
   (thread-start! t)) -| foo, exit value: done

thread-yield!SRFI-18 function
The current thread cooperates. That is, it is suspend for the reaction and the scheduler selects a new thread to be resumed. The scheduler resumes the next avaliable thread. If there is only one thread started in the scheduler, the same thread is resumed. A reaction correspond to the invocation of a scheduler-react! call (see Section Scheduler).


thread-sleep! timeoutSRFI-18 function
The current thread cooperates during exactly timeout reactions (see Scheduler). It is suspended and the scheduler selects a new thread to be resumed. If there is only one thread started in the scheduler, the same thread will be resumed.

(let ((t1 (make-thread 
           (lambda () (thread-sleep! 2) (display 'foo))))
      (t2 (make-thread 
           (lambda () (let loop ((n 1))
                         (display n) 
                         (thread-yield!)
                         (if (< n 5)
                             (loop (+ n 1))))))))
   (thread-start! t1)
   (thread-start! t2)
   (scheduler-start!)) -| 12foo34

thread-terminate! threadSRFI-18 function
Terminates thread at the end of the current reaction.

thread-join! thread [timeout [timeout-val]]SRFI-18 function
The current thread waits until the thread terminates or until the timeout is reached (when supplied). If the timeout is reached, thread-join! returns timeout-val. If thread terminates, thread-join! returns the end-result of the thread or the end-exception if that thread terminates abnormally.

If several threads wait for the termination of the same thread, they are all notified of the termination during the current reaction.

(let* ((t1 (thread-start!
	    (make-thread (lambda ()
			    (thread-sleep! 3)
			    'foo))))
       (t2 (thread-start!
	    (make-thread (lambda ()
			    (print "t1: " (thread-join! t1 1))))))
       (t3 (thread-start!
	    (make-thread (lambda ()
			    (print "t2: " (thread-join! t1 2 'bar))))))
       (t3 (thread-start!
	    (make-thread (lambda ()
			    (print "t3: " (thread-join! t1))))))
       (t4 (thread-start!
	    (make-thread (lambda ()
			    (print "t4: " (thread-join! t1)))))))
   (scheduler-start!))
   -| t1: #|%uncaught-exception [reason: (exception . join-timeout)]|
      t2: bar
      t3: foo
      t4: foo

thread-suspend! threadBigloo function
thread-resume! threadBigloo function
Suspends/resumes the thread at the end of reaction. While suspended a thread is not eligible to get the processor by the scheduler.

thread-await! signal [timeout]Bigloo function
Blocks the thread until signal has been broadcast or until timeout is elapsed. The function thread-await! returns the value associated with the previous emissions of the signal that took place during the reaction.

(let ((t1 (thread-start!
           (make-thread
            (lambda ()
             (display (thread-await! 'foo))
             (display (thread-await! 'bar))))))
      (t2 (thread-start! 
           (make-thread
            (lambda ()
             (broadcast! 'foo 'val1-foo)
             (broadcast! 'foo 'val2-foo)))))
      (t3 (thread-start!
           (make-thread
            (lambda ()
             (thread-sleep! 2)
             (broadcast! 'bar 'val-bar))))))
   (let loop ((n 1))
      (display n)
      (scheduler-react! (default-scheduler))
      (loop (+ n 1))))
  -| 1val2-foo23val-bar456...
The function thread-await! cannot be used to intercept all the signals broadcasted during a reaction. This is illustrated by the following example were obviously thread-await! cannot intercept the emission of the signal:

(thread-start! (make-thread (lambda () 
                               (tread-await! 'foo)
                               (broadcast! 'foo 1))))
(thread-start! (make-thread (lambda () 
                               (broadcast! 'foo 2))))

thread-get-values! signalBigloo function
Terminates the instant for the thread (as thread-yield!) and returns, hence at the next instant, all the values associated with broadcast signal (see Section Signal) during the previous scheduler reaction (see Section Scheduler).

Example:
(thread-start! (make-thread
                  (lambda ()
                     (for-each print (thread-get-values! 'foo)))))
(thread-start! (make-thread
                  (lambda ()
                     (broadcast! 'foo 1)
                     (broadcast! 'foo 'foo)
                     (broadcast! 'foo "blabla"))))
   -| 1
      foo
      blabla
Example:
(let ((t1 (thread-start!
           (make-thread
            (lambda ()
               (for-each print (thread-get-values! 'foo)))
            't1)))
      (t2 (thread-start!
           (make-thread
            (lambda ()
               (broadcast! 'foo (current-thread))
               (thread-yield!)
               ;; this second broadcast won't be intercepted 
               ;; because it occurs during the next reaction
               (broadcast! 'foo (current-thread)))
            't2)))
      (t3 (thread-start!
           (make-thread
            (lambda ()
               (broadcast! 'foo (current-thread))
               (broadcast! 'foo (current-thread)))
            't3))))
   (scheduler-start!))
   -| #<thread:t2>
      #<thread:t3>
      #<thread:t3>

thread-await-values! signal [timeout]Bigloo function
This blocks the current thread until signal has been broadcast. It then returns, at the next instant, all the values associated with all the broadcasts that took place during the instant. It can be defined as:

(define (thread-await-values! signal . tmt)
   (apply thread-await! signal tmt)
   (thread-get-values signal))

thread-await*! signals [timeout]Bigloo function
Wait for one of a list of signals. The function thread-await*! can be compared to the Unix select function. The argument signals is a list of signal identifier. The function thread-await*! blocks the current thread until one of the signal in the list signals is broadcast or until the optional numerical argument timeout is elapsed. If the thread unblocks because the timeout is elapsed, thread-await*! returns #f. Otherwise it returns two values that have to be collected with multiple-value-bind (see Control Features). The first one is the value of the broadcast signal. The second one is the broadcast signal.

Example:
(let ((res #f))
   (thread-start!
    (make-thread (lambda ()
                    (let ((sig* (list 'foo 'bar)))
                       (multiple-value-bind (val1 sig1)
                          (thread-await*! sig*)
                          (multiple-value-bind (val2 sig2)
                             (thread-await*! sig*)
                             (thread-yield!)
                             (multiple-value-bind (val3 sig3)
                                (thread-await*! sig*)
                                (set! res (list sig1 sig2 sig3)))))))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 2)
                    (broadcast! 'foo 1))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 3)
                    (broadcast! 'bar 2))))
   (scheduler-start!)
   res)
  => '(foo foo bar)
A second example using timeouts:
(let ((res #f))
   (thread-start!
    (make-thread (lambda ()
                    (let ((sig* (list 'foo 'bar)))
                       (multiple-value-bind (val1 sig1)
                          (thread-await*! sig* 1)
                          (thread-yield!)
                          (multiple-value-bind (val2 sig2)
                             (thread-await*! sig* 1)
                             (thread-yield!)
                             (multiple-value-bind (val3 sig3)
                                (thread-await*! sig* 2)
                                (set! res (list sig1 sig2 sig3)))))))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 2)
                    (broadcast! 'foo 1))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 3)
                    (broadcast! 'bar 2))))
   (scheduler-start!)
   res)
  => '(#f foo bar)

thread-get-values*! signalsBigloo function
Terminates the instant for the thread (as thread-yield!) and returns, hence at the next instant, all the values associated with all broadcast signals (see Section Signal) during the previous scheduler reaction (see Section Scheduler). The function thread-get-values*! returns an alist made of the scanned signal and their values. That is the length of the returns list is the length of the list signals. If a signal of the list signals has not been broadcast, its associated entry the list returned by thread-get-values*! has an empty cdr.

Example:
(let ((s1 'foo)
      (s2 'bar)
      (s3 'gee)
      (res #f))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 2)
                    (broadcast! 'foo (current-time))
                    (broadcast! 'bar 0))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-await*! (list s1 s2 s3))
                    (set! res (thread-get-values*! (list s1 s2 s3))))))
   (thread-start!
    (make-thread (lambda ()
                    (thread-sleep! 2)
                    (broadcast! 'bar (current-time)))))
   (scheduler-start!)
   res)
  => ((foo 3) (bar 3 0) (gee))
Used with asynchronous signal, the functions thread-await*! and thread-get-values*! can be used to read concurrently, in a non blocking way, several files.

thread-await-values*! signals [timeout]Bigloo function
This blocks the current thread until at least one of signals has been broadcast. It then returns, at the next instant, all the values associated with all the broadcasts that took place during the instant. It can be defined as:

(define (thread-await-values*! signal . tmt)
   (apply thread-await*! signal tmt)
   (thread-get-values*! signal))



17.2.2.2 Scheduler

make-scheduler [envs]Bigloo function
Creates a new scheduler. The optional arguments envs are fair thread environments which will be defined in forthcoming Bigloo releases.

scheduler? objBigloo function
Returns #t if obj is a scheduler. Otherwise returns #f.

current-schedulerBigloo function
Returns the current scheduler. The current scheduler is the scheduler used in the last call to scheduler-react! or scheduler-start!. It always exists a current scheduler. That is, it is optional for an application to create a scheduler.

scheduler-react! [scheduler]Bigloo function
Executes all the treads started (see thread-start!, Section Thread) in the scheduler until all the threads are blocked. A thread is blocked if the has explicitly yield the processor (thread-yield! and thread-sleep!) or because it is waiting a signal (thread-await!). A thread can be selected several times during the same reaction. The function scheduler-react! returns a symbol denoting the state of the scheduler. The possible states are:

  • ready The Scheduler is ready to execute some threads.
  • done All the threads started in the scheduler have terminated.
  • await All the threads started in the scheduler are waiting for a signal.
An invocation of scheduler-react! is called a reaction.

scheduler-start! [arg [scheduler]]Bigloo function
Executes scheduler-react! as long as the scheduler is not done. If the optional argument scheduler is not provided, scheduler-start! uses the current scheduler (see current-scheduler). The optional arg can either be:
  • An integer standing for the number of times scheduler-react! must be called.
  • A procedure f of one argument. The procedure f is invoked after each reaction. It is passed a value i which is the iteration number of the scheduler. The reactions of the scheduler are stopped when f returns #f.
(let* ((s (make-scheduler))
       (t (make-thread (lambda () 
                          (let loop ((n 0))
                             (display n)
                             (thread-yield!)
                             (loop (+ 1 n)))))))
   (scheduler-start! 10 s))
  -| 0123456789

(let* ((s (make-scheduler)) (t (make-thread (lambda () (let loop ((n 0)) (display n) (thread-yield!) (loop (+ 1 n))))))) (scheduler-start! (lambda (i) (read-char)) s)) -| 0123456789

scheduler-terminate! [scheduler]Bigloo function
Terminates all the threads in scheduler.

scheduler-instant [scheduler]Bigloo function
Returns the current reaction number of scheduler. The reaction number is the number of times scheduler-react! has been invoked passing scheduler as argument.

17.2.2.3 Signal

broadcast! signal [val]Bigloo function
Broadcasts signal to all threads started in scheduler immediately, that is during the reaction. This function can only be called from within a running thread. If the optional argument val is omitted, the signal is broadcast with an unspecified value.

(thread-start! (make-thread
		(lambda ()
		   (thread-await! 'foo)
		   (print (scheduler-instant (current-scheduler))))))
(thread-start! (make-thread
		(lambda ()
		   (broadcast! 'foo))))
(scheduler-start!)
  -| 1

scheduler-broadcast! scheduler signal [val]Bigloo function
At the next react broadcasts signal to all threads started in scheduler. This is used to impact running threads from outside any threads. If the optional argument val is omitted, the signal is broadcast with an unspecified value.

make-asynchronous-signal procBigloo function
This function invokes in the background, the procedure proc. This function takes one parameter which is the signal that is broadcast when the invocation returns. When the host operating system supports parallel executions, the invocation of proc is executed in parallel with the waiting thread.

Asynchronous signals can be used to implement non blocking system operations, such as input/output. Here is an example that illustrates how to implement concurrent programs that behaves similarly with Fair Threads and Posix Threads.

(define-expander read
   (lambda (x e)
      (cond-expand
	 (fthread
	  (thread-await!
	   (make-aynchronous-signal
	    (lambda (s)
	       (read ,@(map (lambda (x) (e x e)) (cdr x)))))))
	 (else
	  `(read ,@(map (lambda (x) (e x e)) (cdr x)))))))



17.2.3 SRFI-18

Bigloo implements SRFI-18 (Multithreading support). This SRFI is available at http://srfi.schemers.org/srfi-18/srfi-18.html. One should keep in mind that since the Bigloo scheduler is cooperative Bigloo threads must cooperate at some point in order not to block the execution of other threads. The functions enforcing cooperation are thread-yield!, thread-sleep!, thread-join! and thread-await!. In addition the SRFI-18 mutex-unlock function enforce cooperation.

Thread locking mechanism is common to Fair Threads and Posix Threads (see Thread Common Functions).

current-time [scheduler]SRFI-18 function
Returns the reaction number of scheduler.

time? objSRFI-18 function
time->seconds objSRFI-18 function

join-timeout-exception? objSRFI-18 function
abandoned-mutex-exception? objSRFI-18 function
terminated-thread-exception? objSRFI-18 function
uncaught-exception? objSRFI-18 function
uncaught-exception-reason excSRFI-18 function


17.3 Posix Threads

This section describes the Posix-Like multi-threading Bigloo library. As much as possible, the names exported by this library are compatible with the Fair Threads library (see Section Fair Threads).

17.3.1 Using Posix Threads

The Bigloo modules initialization model does not permit to create threads before the main function is started. In other words, it is unsafe to use the Posix Threads API at the top level of modules. On some particular applications this might work correctly. On other it could produce an error message stating the threads cannot be created or started before the pthread library is initialized.


17.3.2 Threads

thread? objSRFI-18 function
Returns #t if obj is a thread, otherwise returns #f.

current-threadSRFI-18 function
Returns the thread currently running.



make-thread thunk [name]SRFI-18 function
Returns a new thread which is not started yet. The body of the thread is the body of the procedure thunk. The optional argument name can be use to identify the thread. It can be any Bigloo value.

(module example
   (library pthread)
   (main main))

(define (main argv) (make-thread (lambda () (print 1) (thread-yield!) (print 2)) 'my-thread))

thread-start! threadSRFI-18 function
thread-start-joinable! threadSRFI-18 function
Runs a thread created with make-thread.

thread-name threadSRFI-18 function
Returns the name of the thread that has been passed to make-thread.

thread-specific threadSRFI-18 function
thread-specific-set! thread objSRFI-18 function
Returns and sets value in the specific field of the thread. If no value has been set, thread-specific returns an unspecified value.

(let ((t (make-thread (lambda () 
                         (print (thread-specific (current-thread)))))))
   (thread-specific-set! t 'foo)
   (thread-start! t)) -| foo

thread-cleanup threadBigloo function
thread-cleanup-set! thread funBigloo function
Associates a cleanup function to a thread. The cleanup function is called with the thread itself. The cleanup function is executed in a context where current-thread is the thread owning the cleanup function.

(let ((t (make-thread (lambda () 'done) 'foo)))
   (thread-cleanup-set! t (lambda (v) (print (thread-name (current-thread))
					     ", exit value: " v)))
   (thread-start! t)) -| foo, exit value: done

thread-yield!SRFI-18 function
The current thread cooperates.

thread-sleep! timeoutSRFI-18 function
The current thread sleeps for a certain period. It is suspended and the scheduler is free to select a new thread to be resumed. If there is only one thread started in the scheduler, the same thread will be resumed. The time of timeout is used to determine the time the thread must sleep.

Here are the possible types for timeout.

  • date: the thread sleeps at least until the date timeout.
  • real: the thread sleeps at least timeout seconds.
  • fixum, elong, llong: the thread sleeps at least timeout milli-seconds.

thread-terminate! threadSRFI-18 function
Terminates thread as soon as possible.

thread-join! threadSRFI-18 function
The current thread waits until the thread terminates. If thread terminates, thread-join! returns the end-result of the thread or the end-exception if that thread terminates abnormally.

It is possible to wait for the termination of the a thread if and only if it has been started with thread-start-joinable!. In particular, threads started with thread-start cannot be joined.

terminated-thread-exception? objSRFI-18 function
uncaught-exception? objSRFI-18 function
uncaught-exception-reason excSRFI-18 function

17.3.3 Mutexes

Bigloo implements SRFI-18 (Multithreading support). This SRFI is available at http://srfi.schemers.org/srfi-18/srfi-18.html. Thread locking mechanism is common to Fair Threads and Posix Threads (see Thread Common Functions).

17.3.4 Condition Variables

Posix thread condition variables follows the common thread API (see Thread Common Functions).

(module example
  (library pthread)
  (main argv))

(define (main argv) (let ((res #f) (lock (make-mutex)) (cv (make-condition-variable))) (let* ((th1 (thread-start-joinable! (make-thread (lambda () (mutex-lock! lock) (condition-variable-wait! lock cv) (mutex-unlock! lock) (set! res 23))))) (th2 (thread-start! (make-thread (lambda () (mutex-lock! lock) (condition-variable-signal! cv) (mutex-unlock! lock)))))) (thread-join! th1)) res))


This Html page has been produced by Skribe.
Last update Tue Jan 6 18:43:50 2009.