|  | 
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
 | 
Bigloo implements SRFI-18 (Multithreading support). This SRFI is
available at http://srfi.schemers.org/srfi-18/srfi-18.html .
As Bigloo's threads are objects (see Section Object System ),
the SRFI-18's thread specific functions can be used with either the
 pthread or the  fthread library. This section describes the functions that are available independently
of the multi-threading library.
 
Bigloo uses a set of primitive  functions and methods to create,
run and handle thread. For the sake of standardization the name and
semantic  of SRFI-18 has been used. This section presents only the
mandatory functions to program with threads in Bigloo. The most important difference with SRFI-18, is the missing of the
function  make-thread, which is not available for all libraries,
as it can be hard  to predict the type of thread which will be created
if several thread libraries are used simultaneously. As threads are
regular Bigloo objects, they can be created using the
 instantiate syntax. See the Fair Threads  and Posix Threads  
specific sections for more details about thread creation and
examples. The examples given in this section use a generic 
syntax with  instantiate::thread, to run the examples, you will
have to put them in a function in a module (see Section Modules ,
and import one of the libraries using  library module
declaration. 
| 
Returns the current thread.| current-thread | SRFI-18 function |  |  
| 
Returns| thread? obj | SRFI-18 function |  #tifobjis a thread, otherwise returns#f. |  
| 
Returns the name of the| thread-name thread | SRFI-18 function |  thread. |  
| 
| thread-specific thread | SRFI-18 function |  
Returns and sets value in the specific field of the| thread-specific-set! threadobj | SRFI-18 function |  thread. If no
value has been set,thread-specificreturns an unspecified value.
 
 
| (let ((t (instantiate::thread
          (body (lambda ()
                   (print (thread-specific (current-thread))))))))
   (thread-specific-set! t 'foo)
   (thread-start! t)) -| foo
 |  |  
| 
| thread-cleanup thread | Bigloo 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| thread-cleanup-set! threadfun | Bigloo function |  current-threadis the thread owning the
cleanup function.
 
 
| (let ((t (instantiate::thread (body (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-parameter ident | Bigloo function |  
Returns the value of the parameter| thread-parameter-set! identvalue | Bigloo function |  identin the current thread. If
no value is bound to this parameter,#fis 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.
 |  
The next functions have different behaviors depending in the library
used, more details will be given in the specific sections below. 
| 
| thread-start! thread[args] | SRFI-18 function |  
| thread-start-joinable! thread | Bigloo function |  
| thread-join! thread[timeout] | SRFI-18 function |  
| thread-terminate! thread | SRFI-18 function |  
| thread-yield! | SRFI-18 function |  
| thread-sleep! timeout | SRFI-18 function |  |  
Thread locking mechanism is common to Fair Threads and Posix Threads. 
| 
| mutex? obj | SRFI-18 function |  
| make-mutex [ name] | SRFI-18 function |  
| mutex-name mutex | SRFI-18 function |  
| mutex-specific mutex | SRFI-18 function |  
| mutex-specific-set! mutexobj | SRFI-18 function |  
| mutex-state mutex | SRFI-18 function |  
| mutex-lock! mutex[timeout[thread]] | SRFI-18 function, deprecated |  
| mutex-unlock! mutex | SRFI-18 function, deprecated |  
| (let ((m (make-mutex)))
   (thread-start!
    (instantiate::thread
       (body (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!
    (instantiate::thread
       (body (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)
 |  |  
| 
The function| synchronize mutex exp1 exp2 ... | Bigloo form |  synchronizeevaluates the expressionsexp1,exp2, etc. The mutexmutexis acquired and released beforeexp1gets evaluated.  Its value is the value of the evaluated
expression. The formsynchronizeensures that however the form
returns, the mutexmutexis always unlocked.
 
 
| (synchronize mutex
   (print "before read...")
   (read p))
 |  |  
| 
The form| with-lock mutex thunk | Bigloo function, deprecated |  with-lockis similar tosynchronizeinto which it
is expanded.
 The function
 with-lockevaluates the body of thethunk.
The mutexmutexis acquired and released beforethunkgets invoked.
The functionwith-lockmight be implemented as:
 
 
| (define (with-lock mutex thunk)
   (synchronize mutex
      (thunk)))
 |  |  | 17.1.3 Condition Variables
 | 
| 
| condition-variable? obj | SRFI-18 function |  
| make-condition-variable [ name] | SRFI-18 function |  
| condition-variable-name cv | SRFI-18 function |  
| condition-variable-specific cv | SRFI-18 function |  
| condition-variable-specific-set! cvobj | SRFI-18 function |  
| condition-variable-wait! cvmutex[timeout] | Bigloo function |  
| condition-variable-signal! cv | SRFI-18 function |  
| condition-variable-broadcast! cv | SRFI-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
                (condition-variable-wait! (vector-ref sema 2) (vector-ref sema 1))
                (mutex-unlock! (vector-ref sema 1))
                (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!
                 (instantiate::thread
                    (body (lambda ()
                             (semaphore-wait! sema)
                             (set! res (current-time)))))))
            (t2 (thread-start!
                 (instantiate::thread
                    (body (lambda ()
                             (let loop ((n 10))
                                (if (> n 0)
                                    (begin
                                       (semaphore-signal-by! sema 1)
                                       (thread-yield!)
                                       (loop (- n 1)))))))))))
         (scheduler-start!)
         res)))
  => 2
 |  |  
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/indes/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 means 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. 
The Fair Thread library relies on the Posix Thread one, but you don't
need to import the  pthread library, as it is done automatically
when importing the  fthread one. The functions listed in Thread Common Functions  can be used to
manipulates the Fair Thread, but  thread-start-joinable!, as
a fair thread can always join any other fair thread in the same
scheduler.
 17.2.2.1 Thread
| 
Returns a new thread which is not started yet. The body of the thread
is the body of the procedure| instantiate::fthread (body thunk) [(namename)] | Bigloo syntax |  thunk. The optional argumentnamecan be use to identify the thread. It can be any Bigloo value.
 
 
The former thread-start function can be rewritten as follow:| (instantiate::fthread (body (lambda () (print 1) (thread-yield!)
(print 2)))
                      (name 'my-thread))
 |  
 
 
| (define (make-thread body . name)
  (if (pair? name)
      (instantiate::fthread (body body) (name (car name)))
      (instantiate::fthread (body body))))
 |  |  
| 
Runs a thread created with| thread-start! thread[scheduler] | SRFI-18 function |  make-thread. Ifscheduleris
provided, thethreadis started in 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). |  
| 
The current thread cooperates. That is, it is suspended 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 corresponds to the invocation of a| thread-yield! | SRFI-18 function |  scheduler-react!call (see Section Scheduler). |  
| 
The current thread cooperates during exactly| thread-sleep! timeout | SRFI-18 function |  timeoutreactions (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 (instantiate::fthread
             (body (lambda () (thread-sleep! 2) (display 'foo)))))
      (t2 (instantiate::fthread
             (body (lambda () (let loop ((n 1))
                                 (display n) 
                                 (thread-yield!)
                                 (if (< n 5)
                                 (loop (+ n 1)))))))))
   (thread-start! t1)
   (thread-start! t2)
   (scheduler-start!)) -| 12foo34
 |  |  
| 
Terminates| thread-terminate! thread | SRFI-18 function |  threadat the end of the current reaction. |  
| 
The current thread waits until| thread-join! thread[timeout[timeout-val]] | SRFI-18 function |  threadterminates or untiltimeoutis reached (when supplied). If thetimeoutis
reached,thread-join!returnstimeout-val. Ifthreadterminates,thread-join!returns the end-result of thethreador 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!
            (instantiate::fthread
               (body (lambda () (thread-sleep! 3) 'foo)))))
       (t2 (thread-start!
            (instantiate::fthread
               (body (lambda () (print "t1: " (thread-join! t1 1)))))))
       (t3 (thread-start!
            (instantiate::fthread
               (body (lambda () (print "t2: " (thread-join! t1 2 'bar)))))))
       (t3 (thread-start!
            (instantiate::fthread
               (body (lambda () (print "t3: " (thread-join! t1)))))))
       (t4 (thread-start!
            (instantiate::fthread
               (body (lambda () (print "t4: " (thread-join! t1))))))))
   (scheduler-start!))
   -| t1: #|%uncaught-exception [reason: (exception . join-timeout)]|
      t2: bar
      t3: foo
      t4: foo
 |  thread-join!can be used to wait for a Posix Thread
termination. Thepthreadobject must be started withthread-start-joinable!. |  
| 
| thread-suspend! thread | Bigloo function |  
Suspends/resumes the| thread-resume! thread | Bigloo function |  threadat the end of reaction. While suspended
a thread is not eligible to get the processor by the scheduler. |  
| 
Blocks the thread until| thread-await! signal[timeout] | Bigloo function |  signalhas been broadcast or untiltimeouthas elapsed. The functionthread-await!returns
the value associated with the previous emissions of the signal that
took place during the reaction.
 
 
The function| (let ((t1 (thread-start! (instantiate::fthread
                            (body (lambda ()
                                     (display (thread-await! 'foo))
                                     (display (thread-await! 'bar)))))))
      (t2 (thread-start! (instantiate::fthread
                            (body (lambda ()
                                     (broadcast! 'foo 'val1-foo)
                                     (broadcast! 'foo 'val2-foo))))))
      (t3 (thread-start! (instantiate::fthread
                            (body (lambda ()
                                     (thread-sleep! 2)
                                     (broadcast! 'bar 'val-bar)))))))
   (let loop ((n 1))
      (display n)
      (scheduler-react! (default-scheduler))
      (loop (+ n 1))))
  -| 1val2-foo23val-bar456...
 |  thread-await!cannot be used to intercept all the signals
broadcast during a reaction. This is illustrated by the following example
where obviouslythread-await!cannot intercept the emission of the
signal:
 
 
| (thread-start! (instantiate::fthread (body (lambda () 
                                              (thread-await! 'foo)
                                              (broadcast! 'foo 1)))))
(thread-start! (instantiate::fthread (body (lambda () 
                                              (broadcast! 'foo 2)))))
 |  |  
| 
Terminates the instant for the thread (as| thread-get-values! signal | Bigloo function |  thread-yield!) and
returns, hence at the next instant, all the values associated with
broadcastsignal(see Section Signal) during the previous scheduler
reaction (see Section Scheduler).
 Example:
 
Example:| (thread-start! (instantiate::fthread
                  (body (lambda ()
                           (for-each print (thread-get-values! 'foo))))))
(thread-start! (instantiate::fthread
                  (body (lambda ()
                           (broadcast! 'foo 1)
                           (broadcast! 'foo 'foo)
                           (broadcast! 'foo "blabla")))))
   -| 1
      foo
      blabla
 |  
| (let ((t1 (thread-start!
           (instantiate::fthread
              (body (lambda ()
                       (for-each print (thread-get-values! 'foo))))
              (name 't1))))
      (t2 (thread-start!
           (instantiate::fthread
              (body (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))))
              (name 't2))))
      (t3 (thread-start!
           (instantiate::fthread
              (body (lambda ()
                       (broadcast! 'foo (current-thread))
                       (broadcast! 'foo (current-thread))))
              (name 't3)))))
   (scheduler-start!))
   -| #<thread:t2>
      #<thread:t3>
      #<thread:t3>
 |  |  
| 
This blocks the current thread until| thread-await-values! signal[timeout] | Bigloo function |  signalhas 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))
 |  |  
| 
Wait for one of a list of signals. The function| thread-await*! signals[timeout] | Bigloo function |  thread-await*!can be compared to the Unixselectfunction. The argumentsignalsis a list of signal identifier. The functionthread-await*!blocks the current thread until one of the signal in 
the listsignalsis broadcast or until the optional numerical argumenttimeoutis elapsed. If the thread unblocks because the timeout is 
elapsed,thread-await*!returns#f. Otherwise it returns two
values that have to be collected withmultiple-value-bind(see
Control Features). The first one is the value of the broadcast
signal. The second one is the broadcast signal.
 Example:
 
A second example using timeouts:| (let ((res #f))
   (thread-start!
    (instantiate::fthread
       (body (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!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 2)
                (broadcast! 'foo 1)))))
   (thread-start!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 3)
                (broadcast! 'bar 2)))))
   (scheduler-start!)
   res)
  => '(foo foo bar)
 |  
| (let ((res #f))
   (thread-start!
    (instantiate::fthread
       (body (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!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 2)
                (broadcast! 'foo 1)))))
   (thread-start!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 3)
                (broadcast! 'bar 2)))))
   (scheduler-start!)
   res)
  => '(#f foo bar)
 |  |  
| 
Terminates the instant for the thread (as| thread-get-values*! signals | Bigloo function |  thread-yield!) and
returns, hence at the next instant, all the values associated with
all broadcastsignals(see Section Signal) during the previous 
scheduler reaction (see Section Scheduler). The functionthread-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 listsignals. If a signal of the listsignalshas not
been broadcast, its associated entry the list returned bythread-get-values*!has an emptycdr.
 Example:
 
Used with asynchronous signal, the functions| (let ((s1 'foo)
      (s2 'bar)
      (s3 'gee)
      (res #f))
   (thread-start!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 2)
                (broadcast! 'foo (current-time))
                (broadcast! 'bar 0)))))
   (thread-start!
    (instantiate::fthread
       (body (lambda ()
                (thread-await*! (list s1 s2 s3))
                (set! res (thread-get-values*! (list s1 s2 s3)))))))
   (thread-start!
    (instantiate::fthread
       (body (lambda ()
                (thread-sleep! 2)
                (broadcast! 'bar (current-time))))))
   (scheduler-start!)
   res)
  => ((foo 3) (bar 3 0) (gee))
 |  thread-await*!andthread-get-values*!can be used to read concurrently, in a non 
blocking way, several files. |  
| 
This blocks the current thread until at least one of| thread-await-values*! signals[timeout] | Bigloo function |  signalshas 
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
| 
Creates a new scheduler. The optional boolean argument| make-scheduler [ strict-order?] [envs] | Bigloo function |  strict-order?is used to ask the scheduler to always schedule
the threads in the same order, it defaults to#f. The optional
argumentsenvsare fair thread environments which will be
defined in forthcoming Bigloo releases. |  
| 
| scheduler-strict-order? | Bigloo function |  
Gets or sets the strict scheduling policy of the scheduler. If set,
the threads will always be scheduled in the same order, until their
termination. By default, it is set to false, which improve
performances when there is a lot of thread to schedule.| scheduler-strict-order?-set! bool | Bigloo function |  |  
| 
Returns| scheduler? obj | Bigloo function |  #tifobjis a scheduler. Otherwise returns#f. |  
| 
Returns| scheduler? obj | Bigloo function |  #tifobjis a scheduler. Otherwise returns#f. |  
| 
Returns the current scheduler. The current scheduler is the scheduler
which currently schedules the current thread. This value is not
mutable, as it is set during the call to| current-scheduler | Bigloo function |  thread-start!. |  
| 
Sets or gets the default scheduler. The default scheduler is the
scheduler that will be used in the calls to| default-scheduler [ scheduler] | Bigloo function |  scheduler-react!,scheduler-start!orthread-start!if not specified.
It always exists a default scheduler. That is, it is optional for an
application to create a scheduler. |  
| 
Executes all the threads started (see| scheduler-react! [ scheduler] | Bigloo function |  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!andthread-sleep!) or because it is waiting
a signal (thread-await!). A thread
can be selected several times during the same reaction.
The functionscheduler-react!returns a symbol denoting the
state of the scheduler. The possible states are:
 
 An invocation ofreadyThe Scheduler is ready to execute some threads.doneAll the threads started in the scheduler have terminated.awaitAll the threads  started in the scheduler are waiting for
      a signal.
 scheduler-react!is called a reaction. |  
| 
Executes| scheduler-start! [ arg[scheduler]] | Bigloo function |  scheduler-react!as long as the scheduler is not done.
If the optional argumentscheduleris not provided,scheduler-start!uses the current scheduler 
(seecurrent-scheduler). The optionalargcan either be:An integer standing for the number of times scheduler-react!must be called.A procedure fof one argument. The procedurefis invoked after each reaction. It is passed a valueiwhich is 
      the iteration number of the scheduler. The reactions of the scheduler
      continue whilefreturns#f.
 
| (let* ((s (make-scheduler))
       (t (instantiate::fthread
             (body (lambda () 
                      (let loop ((n 0))
                         (display n)
                         (thread-yield!)
                         (loop (+ 1 n))))))))
   (scheduler-start! 10 s))
  -| 0123456789
 (let* ((s (make-scheduler))
       (t (instantiate::fthread
             (body (lambda () 
                      (let loop ((n 0))
                         (display n)
                         (thread-yield!)
                         (loop (+ 1 n))))))))
   (scheduler-start! (lambda (i) (read-char)) s))
  -| 0123456789
 |  |  
| 
Terminates all the threads in| scheduler-terminate! [ scheduler] | Bigloo function |  scheduler. |  
| 
Returns the current reaction number of| scheduler-instant [ scheduler] | Bigloo function |  scheduler. The reaction
number is the number of timesscheduler-react!has been invoked
passingscheduleras argument. |  17.2.2.3 Signal
| 
Broadcasts| broadcast! signal[val] | Bigloo function |  signalto all threads started inschedulerimmediately, that is during the reaction. This function can only
be called from within a running thread. If the optional argumentvalis omitted, thesignalis broadcast with an unspecified value.
 
 
| (thread-start! (instantiate::fthread
                  (body (lambda ()
                           (thread-await! 'foo)
                           (print (scheduler-instant (current-scheduler)))))))
(thread-start! (instantiate::fthread
                  (body (lambda ()
                           (broadcast! 'foo)))))
(scheduler-start!)
  -| 1
 |  |  
| 
At the next react broadcasts| scheduler-broadcast! schedulersignal[val] | Bigloo function |  signalto all threads started 
inscheduler. This is used to impact running threads from outside 
any threads. If the optional argumentvalis omitted, thesignalis broadcast with an unspecified value. |  
| 
This function invokes in the background, the procedure| make-asynchronous-signal proc | Bigloo function |  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 ofprocis 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)))))))
 |  |  
This section presents the functions that are not necessary to Bigloo
but supported for compliance with SRFI-18, provided by the Fair Thread
library. 
| 
Returns the reaction number of| current-time [ scheduler] | SRFI-18 function |  scheduler. |  
| 
| time? obj | SRFI-18 function |  
| time->seconds obj | SRFI-18 function |  |  
| 
| join-timeout-exception? obj | SRFI-18 function |  
| abandoned-mutex-exception? obj | SRFI-18 function |  
| terminated-thread-exception? obj | SRFI-18 function |  
| uncaught-exception? obj | SRFI-18 function |  
| uncaught-exception-reason exc | SRFI-18 function |  |  
This section describes two Posix-Like multi-threading Bigloo libraries.
The two libraries,  pthread, and  srfi-18 are all the same
but the  mutex-state function that returns different results.
Because of these differences that might seem thin at first glance,
the  pthread library is significantly faster than the  srfi-18
library. For that reason, it is recommended to use the  pthread
library instead of the  srfi-18 library that is mostly supported
for backward compatibility. 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. 
| 
| instantiate::pthread (body thunk) [(namename)] | Bigloo syntax |  
Returns a new thread which is not started yet. The body of the thread
is the body of the procedure| make-thread thunk[name] | SRFI-18 function |  thunk. The optional argumentnamecan be use to identify the thread. It can be any Bigloo value.
 Warning: the
 make-threadfunction is deprecated, but
still provided for a backward compatibility with previous release of
Bigloo. The use of this function is highly discouraged, in
favor of theinstantiate::pthreadform.
 
 
| (module example
   (library pthread)
   (main main))
 (define (main argv)
   (make-thread 
    (lambda () 
       (print 1)
       (thread-yield!)
       (print 2)) 
    'my-thread))
 |  |  
| 
| thread-start! thread | SRFI-18 function |  
Runs a thread created with| thread-start-joinable! thread | SRFI-18 function |  instantiate::pthread. By default,
threads are detached, and thus, they cannot be joined. |  
| 
The current thread cooperates.| thread-yield! | SRFI-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| thread-sleep! timeout | SRFI-18 function |  timeoutis used to determine the
time the thread must sleep.
 Here are the possible types for
 timeout.
 
 date: the thread sleeps at least until the datetimeout.real: the thread sleeps at leasttimeoutseconds.fixum,elong,llong: the thread sleeps at leasttimeoutmilli-seconds.
 |  
| 
Terminates| thread-terminate! thread | SRFI-18 function |  threadas soon as possible. |  
| 
The current thread waits until the| thread-join! thread[timeout] | SRFI-18 function |  threadterminates. Ifthreadterminates,thread-join!returns the end-result of thethreador 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 withthread-start!cannot be joined.
 The optional argument
 timeout, forces to wait at fortimeoutmilli-seconds for the thread to terminate. Note that not
all systems support this facility. When supported, thecond-expand(see see SRFIs)pthread-timedjoinis
defined. When the timeout expires some systems, raise an error. Other
systems abort silently.
 
 |  
| 
| terminated-thread-exception? obj | SRFI-18 function |  
| uncaught-exception? obj | SRFI-18 function |  
| uncaught-exception-reason exc | SRFI-18 function |  |  
Thread locking mechanism is common to Fair Threads and Posix Threads
(see Thread Common Functions ). 
| 
Returns the symbol| mutex-state mutex | SRFI-18 function |  lockedwhen the mutex is locked by a thread.
Otherwise, it returns the symbolunlocked. |  | 17.3.4 Condition Variables
 | 
Posix thread condition variables follows the common thread API
(see Thread Common Functions ). 
| (module example
  (library pthread)
  (main main))
 (define (main argv)
   (let ((res #f)
	 (lock (make-mutex))
	 (cv (make-condition-variable)))
      (thread-join!
       (thread-start-joinable!
	(instantiate::pthread
	   (body (lambda ()
		    (mutex-lock! lock)
		    (thread-start!
		     (instantiate::pthread
			(body (lambda ()
				 (mutex-lock! lock)
				 (condition-variable-signal! cv)
				 (mutex-unlock! lock)))))
		    (condition-variable-wait! cv lock)
		    (set! res 23) 
		    (mutex-unlock! lock))))))
      res))
 |  
| 
Returns information about the state of the mutex. The possible results are:| mutex-state mutex | SRFI-18 function |  
 
 Examples: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 statesymbol abandoned: the mutex is in the unlocked/abandoned statesymbol 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))))
 
 
 |  |  
The Fair Threads  library is ``Posix Threads'' safe, which means it
is possible to use at the same time both libraries. In other words, it
is possible to embed one fair scheduler into a Posix thread. Here is a little example with two schedulers started into two
different Posix threads, each schedulers running two fair threads. 
| (module mix_threads
   (library fthread pthread)
   (main main))
 (define *f1* 0)
(define *f2* 0)
 
 (define (main args)
   (let ((s1 (make-scheduler #t))
	 (s2 (make-scheduler #t))
	 
	 (f1a (instantiate::fthread
		 (body (lambda ()
			  (let loop ()
			     (print "f1a: " *f1* " " (current-thread))
			     (set! *f1* (+ 1 *f1*))
			     (thread-yield!)
			     (loop))))))
	 
	 (f1b (instantiate::fthread
		 (body (lambda ()
			  (let loop ()
			     (print "f1b: " *f1* " " (current-thread))
			     (set! *f1* (+ 1 *f1*))
			     (thread-yield!)
			     (loop))))))
	 
	 (f2a (instantiate::fthread
		 (body (lambda ()
			  (let loop ()
			     (print "f2a: " *f2* " " (current-thread))
			     (set! *f2* (+ 1 *f2*))
			     (thread-yield!)
			     (loop))))))
	 
	 (f2b (instantiate::fthread
		 (body (lambda ()
			  (let loop ()
			     (print "f2b: " *f2* " " (current-thread))
			     (set! *f2* (+ 1 *f2*))
			     (thread-yield!)
			     (loop)))))))
      
      (let* ((p1 (instantiate::pthread
		   (body (lambda ()
			    ;; Sets the thread's specific scheduler
			    (default-scheduler s1)
			    (scheduler-start! 5)))))
	     
	    (p2 (instantiate::pthread
		   (body (lambda ()
			    ;; Sets the thread's specific scheduler
			    (default-scheduler s2)
			    ;; One reaction for s2
			    (scheduler-react!)
			    ;; Starts s1
			    (thread-start-joinable! p1)
			    ;; Do three reactions
			    (scheduler-start! 3)
			    ;; Waits for p1/s1 termination
			    (thread-join! p1)
			    ;; The final reaction
			    (scheduler-react!))))))
	 
	 (thread-start! f1a s1)
	 (thread-start! f1b s1)
	 (thread-start! f2a s2)
	 (thread-start! f2b s2)
	 
	 (thread-join! (thread-start-joinable! p2)))))
 |  |