<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="polydoc.xsl"?>
<polydoc>
<title>Signature THREAD Structure Thread</title>
<navigation>
<parent href="Basis.html">Basis</parent>
<previous href="SingleAssignment.xml">SingleAssignment</previous>
<next href="Universal.xml">Universal</next>
</navigation>
<headtext>
<p>Earlier versions of Poly/ML have provided a form of concurrent execution through 
  the Process structure. Version 5.1 introduces 
  new thread primitives in the Thread structure. This structure is modelled on 
  the Posix thread (pthread) package but simplified and modified for ML. The aim 
  is to provide an efficient implementation of parallelism particularly to enable 
  ML programs to make use of multi-core processors while minimising the changes 
  needed to existing code. The Process structure will continue to be available 
  as a library written on top of these primitives but new programs should use 
  the Thread structure directly.</p>
<p>The thread package differs from pthreads in a number of ways. 
There is no join function to wait for the completion of a thread. 
This can be written using mutexes and condition variables. 
Cancellation and signal handling are combined into the interrupt
functions. (The Poly/ML Signal structure handles signals for all the
threads together).  The effect of explicit cancellation is achieved
using the interrupt function.  This causes an interrupt to be
generated in a specific thread.  Alternatively an interrupt can be
broadcast to all threads.  This is most likely to be used
interactively to kill threads that appear to have gone out of
control.  The normal top-level handler for a console interrupt will
generate this.  Threads can choose how or whether they respond to
these interrupts.  A thread that is doing processor-intensive work
probably needs to be able to be interrupted asynchronously whereas if
it is communicating with other threads the presence of asynchronous
interrupts makes correct programming difficult.
</p></headtext>
<topdecs>
<summary>signature THREAD:
sig
    exception Thread: string
    structure Thread:
    sig
        eqtype thread 
        datatype threadAttribute =
            EnableBroadcastInterrupt of bool |
            InterruptState of interruptState |
            MaximumMLStack of int option
        and interruptState =
            InterruptDefer |
            InterruptSynch |
            InterruptAsynch |
            InterruptAsynchOnce
        val fork: (unit -&gt; unit) * threadAttribute list -&gt; thread
        val exit: unit -&gt; unit
        val isActive: thread -&gt; bool
        val equal: thread * thread -&gt; bool
        val self: unit -&gt; thread
        exception Interrupt
        val interrupt: thread -&gt; unit
        val broadcastInterrupt: unit -&gt; unit
        val testInterrupt: unit -&gt; unit
        val kill: thread -&gt; unit
        val getLocal: 'a Universal.tag -&gt; 'a option
        and setLocal: 'a Universal.tag * 'a -&gt; unit
        val setAttributes: threadAttribute list -&gt; unit
        val getAttributes: unit -&gt; threadAttribute list
        val numProcessors: unit -&gt; int
        and numPhysicalProcessors: unit -&gt; int option
    end
    structure Mutex:
    sig
        type mutex 
        val mutex: unit -&gt; mutex
        val lock: mutex -&gt; unit
        val unlock: mutex -&gt; unit
        val trylock: mutex -&gt; bool
    end
    structure ConditionVar:
    sig
        type conditionVar 
        val conditionVar: unit -&gt; conditionVar
        val wait: conditionVar * Mutex.mutex -&gt; unit
        val waitUntil: conditionVar * Mutex.mutex * Time.time -&gt; bool
        val signal: conditionVar -&gt; unit
        val broadcast: conditionVar -&gt; unit
    end
end
structure Thread: THREAD
</summary>
<bindings><binding>
<code>exception <definition>Thread</definition>: string
</code>
<text><p>The Thread exception can be raised by various of the functions in the
       structure if they detect an error.</p></text>
</binding>
<binding>
<code>structure <definition>Thread</definition>
</code>
<text><p></p></text>
</binding>
<binding>
<code>eqtype <definition>thread</definition> 
</code>
<text><p>The type of a thread identifier.</p></text>
</binding>
<binding>
<code>datatype <definition>threadAttribute</definition> =
    EnableBroadcastInterrupt of bool |
    InterruptState of interruptState |
    MaximumMLStack of int option
and <definition>interruptState</definition> =
    InterruptDefer |
    InterruptSynch |
    InterruptAsynch |
    InterruptAsynchOnce
</code>
<text><p>The type of a thread attribute. Thread attributes are
            properties of the thread that are set initially when the thread is
            created but can subsequently be modified by the thread itself.  The
            thread attribute type may be extended in the future to include things
            like scheduling priority. The current thread attributes control the
            way interrupt exceptions are delivered to the thread.</p>
<p>            <identifier>EnableBroadcastInterrupt</identifier> controls whether the thread will receive an interrupt sent using
            <identifier>broadcastInterrupt</identifier> or as a result of pressing the console interrupt
            key. If this is false the thread will not receive them.  The default
            for a new thread if this is not specified is false.</p>
<p>            <identifier>InterruptState</identifier> controls when and whether interrupts are delivered to the 
            thread. This includes broadcast interrupts and also interrupts directed at 
            a specific thread with the interrupt call.
            <identifier>InterruptDefer</identifier> means the thread 
            will not receive any interrupts. However, if the thread has previously been 
            interrupted the interrupt may be delivered when the thread calls setAttributes 
            to change its interrupt state. <identifier>InterruptSynch</identifier>
            means interrupts are delivered 
            synchronously. An interrupt will be delayed until an interruption point. An 
            interruption point is one of: <identifier>testInterrupt</identifier>,
            <identifier>ConditionVar.wait</identifier>, <identifier>ConditionVar.waitUntil</identifier>
            and various library calls that may block, such as IO calls, pause etc. N.B. 
            <identifier>Mutex.lock</identifier> is not an interruption point even though it can result in a thread 
            blocking for an indefinite period. <identifier>InterruptAsynch</identifier> means interrupts are delivered 
            asynchronously i.e. at a suitable point soon after they are triggered.
            <identifier>InterruptAsynchOnce</identifier>
            means that only a single interrupt is delivered asynchronously after which 
            the interrupt state is changed to <identifier>InterruptSynch</identifier>. It allows a thread to tidy 
            up and if necessary indicate that it has been interrupted without the risk 
            of a second asynchronous interrupt occurring in the handler for the first 
            interrupt. If this attribute is not specified when a thread is created the 
            default is <identifier>InterruptSynch</identifier>.</p>
<p>            <identifier>MaximumMLStack</identifier> was added in version 5.5.3. It controls the maximum size the 
            ML stack may grow to. It is an option type where NONE allows the stack to 
            grow to the limit of the available memory whereas SOME n limits the stack 
            to n words. This is approximate since there is some rounding involved. When 
            the limit is reached the thread is sent an Interrupt exception.</p></text>
</binding>
<binding>
<code>val <definition>fork</definition> : (unit -&gt; unit) * threadAttribute list -&gt; thread
</code>
<text><p>Fork a thread. Starts a new thread running 
          the function argument. The attribute list gives initial values for thread attributes 
          which can be modified by the thread itself. Any unspecified attributes take 
          default values. The thread is terminated when the thread function returns, if 
          it raises an uncaught exception or if it calls <identifier>exit</identifier>;</p></text>
</binding>
<binding>
<code>val <definition>exit</definition> : unit -&gt; unit
</code>
<text><p>Terminate this thread. </p></text>
</binding>
<binding>
<code>val <definition>isActive</definition> : thread -&gt; bool
</code>
<text><p>Test if a thread is still running or has terminated.  This function should be
          used with care.  The thread may be on the point of terminating and still appear
          to be active.</p></text>
</binding>
<binding>
<code>val <definition>equal</definition> : thread * thread -&gt; bool
</code>
<text><p>Test whether thread ids are the same.  This is provided for backwards compatibility
          since <identifier>thread</identifier> is an eqtype. </p></text>
</binding>
<binding>
<code>val <definition>self</definition> : unit -&gt; thread
</code>
<text><p>Return the thread identifier for the current thread. </p></text>
</binding>
<binding>
<code>exception <definition>Interrupt</definition>
</code>
<text><p></p></text>
</binding>
<binding>
<code>val <definition>interrupt</definition> : thread -&gt; unit
</code>
<text><p>Send an Interrupt exception to a specific thread.  When and indeed whether
           the exception is actually delivered will depend on the interrupt state
           of the target thread.  Raises Thread if the thread is no longer running,
           so an exception handler should be used unless the thread is known to
           be blocked. </p></text>
</binding>
<binding>
<code>val <definition>broadcastInterrupt</definition> : unit -&gt; unit
</code>
<text><p>Send an interrupt exception to every thread which is set to accept it. </p></text>
</binding>
<binding>
<code>val <definition>testInterrupt</definition> : unit -&gt; unit
</code>
<text><p>If this thread is handling interrupts synchronously, test to see 
           if it has been interrupted.  If so it raises the
           <identifier>Interrupt</identifier> exception. </p></text>
</binding>
<binding>
<code>val <definition>kill</definition> : thread -&gt; unit
</code>
<text><p>Terminate a thread. This should be used as a last resort.  Normally
           a thread should be allowed to clean up and terminate by using the
           interrupt call.  Raises Thread if the thread is no longer running,
           so an exception handler should be used unless the thread is known to
           be blocked. </p></text>
</binding>
<binding>
<code>val <definition>getLocal</definition> : 'a Universal.tag -&gt; 'a option
and <definition>setLocal</definition> : 'a Universal.tag * 'a -&gt; unit
</code>
<text><p>Get and set thread-local store for the calling thread. The store is a
           tagged associative memory which is initially empty for a new thread.
           A thread can call setLocal to add or replace items in its store and
           call getLocal to return values if they exist.  The Universal structure
           contains functions to make new tags as well as injection, projection and
           test functions. </p></text>
</binding>
<binding>
<code>val <definition>setAttributes</definition> : threadAttribute list -&gt; unit
</code>
<text><p>Change the specified attribute(s) for the calling thread.  Unspecified
           attributes remain unchanged. </p></text>
</binding>
<binding>
<code>val <definition>getAttributes</definition> : unit -&gt; threadAttribute list
</code>
<text><p>Get the values of attributes. </p></text>
</binding>
<binding>
<code>val <definition>numProcessors</definition> : unit -&gt; int
and <definition>numPhysicalProcessors</definition> : unit -&gt; int option
</code>
<text><p>Return the number of processors that will be used to run threads
           and the number of physical processors if that is available. </p></text>
</binding>
<binding>
<code>structure <definition>Mutex</definition>
</code>
<text><p></p></text>
</binding>
<binding>
<code>type <definition>mutex</definition> 
</code>
<text><p>A mutex provides simple mutual exclusion.  A thread can lock
           a mutex and until it unlocks it no other thread will be able to lock it.
           Locking and unlocking are intended to be fast in the situation when
           there is no other process attempting to lock the mutex.
           These functions may not work correctly if an asynchronous interrupt
           is delivered during the calls.  A thread should use synchronous interrupt
           when using these calls. </p></text>
</binding>
<binding>
<code>val <definition>mutex</definition> : unit -&gt; mutex
</code>
<text><p>Make a new mutex </p></text>
</binding>
<binding>
<code>val <definition>lock</definition> : mutex -&gt; unit
</code>
<text><p>Lock a mutex.  If the mutex is currently locked the thread is
           blocked until it is unlocked.  If a thread tries to lock a mutex that
           it has previously locked the thread will deadlock.
           N.B.  <identifier>thread</identifier> is not an interruption point
           (a point where synchronous
           interrupts are delivered) even though a thread can be blocked indefinitely. </p></text>
</binding>
<binding>
<code>val <definition>unlock</definition> : mutex -&gt; unit
</code>
<text><p>Unlock a mutex and allow any waiting threads to run.  The behaviour
           if the mutex was not previously locked by the calling thread is undefined.  </p></text>
</binding>
<binding>
<code>val <definition>trylock</definition> : mutex -&gt; bool
</code>
<text><p>Attempt to lock the mutex.  Returns true if the mutex was not
           previously locked and has now been locked by the calling thread.  Returns
           false if the mutex was previously locked, including by the calling thread. </p></text>
</binding>
<binding>
<code>structure <definition>ConditionVar</definition>
</code>
<text><p></p></text>
</binding>
<binding>
<code>type <definition>conditionVar</definition> 
</code>
<text><p>Condition variables are used to provide communication
           between threads.  A condition variable is used in conjunction with a mutex
           and usually a reference to establish and test changes in state.  The normal
           use is for one thread to lock a mutex, test the reference and then wait on
           the condition variable, releasing the lock on the mutex while it does so.
           Another thread may then lock the mutex, update the reference, unlock the
           mutex, and signal the condition variable.  This wakes up the first thread
           and reacquires the lock allowing the thread to test the updated reference
           with the lock held.
           More complex communication mechanisms, such as blocking channels, can
           be written in terms of condition variables. </p></text>
</binding>
<binding>
<code>val <definition>conditionVar</definition> : unit -&gt; conditionVar
</code>
<text><p>Make a new condition variable. </p></text>
</binding>
<binding>
<code>val <definition>wait</definition> : conditionVar * Mutex.mutex -&gt; unit
</code>
<text><p>Release the mutex and block until the condition variable is signalled. When 
            wait returns the mutex will have been re-acquired.</p>
<p>            If the thread is handling interrupts synchronously this function can be interrupted 
            using the <identifier>Thread.interrupt</identifier> function or, if the thread is set to 
            accept broadcast interrupts, <identifier>Thread.broadcastInterrupt</identifier>. The thread 
            will re-acquire the mutex before the exception is delivered. An exception 
            will only be delivered in this case if the interrupt is sent before the condition 
            variable is signalled. If the interrupt is sent after the condition variable 
            is signalled the function will return normally even if it has not yet re-acquired 
            the mutex. The interrupt state will be delivered on the next call to &amp;quot;wait&amp;quot;, 
            <identifier>Thread.testInterrupt</identifier> or other blocking call.</p>
<p>            A thread should never call this function if it may receive an asynchronous 
            interrupt. It should always set its interrupt state to either
            <identifier>InterruptSynch</identifier> 
            or <identifier>InterruptDefer</identifier> beforehand.
            An asynchronous interrupt may leave the condition 
            variable and the mutex in an indeterminate state and could lead to deadlock.</p>
<p>            A condition variable should only be associated with one mutex at a time. 
            All the threads waiting on a condition variable should pass the same mutex 
            as argument.</p></text>
</binding>
<binding>
<code>val <definition>waitUntil</definition> : conditionVar * Mutex.mutex * Time.time -&gt; bool
</code>
<text><p>As wait except that it blocks until either the condition
           variable is signalled or the time (absolute) is reached.
           Returns true if condition variable was signalled and false if
           the time-out was reached.  Either way the mutex is reacquired so
           there may be a further delay if it is held by another thread. </p></text>
</binding>
<binding>
<code>val <definition>signal</definition> : conditionVar -&gt; unit
</code>
<text><p>Wake up one thread if any are waiting on the condition variable. 
          If there are several threads waiting for the condition variable one will be 
          selected to run and will run as soon as it has re-acquired the lock. </p></text>
</binding>
<binding>
<code>val <definition>broadcast</definition> : conditionVar -&gt; unit
</code>
<text><p>Wake up all threads waiting on the condition variable. </p></text>
</binding>
</bindings>
</topdecs>
<tailtext>
<p></p></tailtext>
</polydoc>
