<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta name="robots" content="index,nofollow">



<title>MLtonThread - MLton Standard ML Compiler (SML Compiler)</title>
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="all" href="common.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="screen" href="screen.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="print" href="print.css">


<link rel="Start" href="Home">


</head>

<body lang="en" dir="ltr">

<table bgcolor = lightblue cellspacing = 0 style = "border: 0px;" width = 100%>
  <tr>
    <td style = "
		border: 0px;
		color: darkblue; 
		font-size: 150%;
		text-align: left;">
      <a class = mltona href="Home">MLton 20051202</a>
    <td style = "
		border: 0px;
		font-size: 150%;
		text-align: center;
		width: 50%;">
      MLtonThread
    <td style = "
		border: 0px;
		text-align: right;">
      <table cellspacing = 0 style = "border: 0px">
        <tr style = "vertical-align: middle;">
      </table>
  <tr style = "background-color: white;">
    <td colspan = 3
	style = "
		border: 0px;
		font-size:70%;
		text-align: right;">
      <a href = "Home">Home</a>
      &nbsp;<a href = "Index">Index</a>
      &nbsp;
</table>
<div id="content" lang="en" dir="ltr">

<pre class=code>
<B><FONT COLOR="#0000FF">signature</FONT></B> MLTON_THREAD =
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#0000FF">structure</FONT></B> AtomicState:
         <B><FONT COLOR="#0000FF">sig</FONT></B>
            <B><FONT COLOR="#A020F0">datatype</FONT></B><FONT COLOR="#228B22"><B> t </FONT></B>=<FONT COLOR="#228B22"><B> <FONT COLOR="#B8860B">NonAtomic</FONT> </FONT></B>|<FONT COLOR="#228B22"><B> <FONT COLOR="#B8860B">Atomic</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> int
         </FONT></B><B><FONT COLOR="#0000FF">end</FONT></B>

      <B><FONT COLOR="#A020F0">val</FONT></B> atomically: (unit -&gt; 'a) -&gt; 'a
      <B><FONT COLOR="#A020F0">val</FONT></B> atomicBegin: unit -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> atomicEnd: unit -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> atomicState: unit -&gt; AtomicState.t

      <B><FONT COLOR="#0000FF">structure</FONT></B> Runnable:
         <B><FONT COLOR="#0000FF">sig</FONT></B>
            <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> t
         </FONT></B><B><FONT COLOR="#0000FF">end</FONT></B>

      <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> 'a t

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> atomicSwitch: ('a t -&gt; Runnable.t) -&gt; 'a
      <B><FONT COLOR="#A020F0">val</FONT></B> new: ('a -&gt; unit) -&gt; 'a t
      <B><FONT COLOR="#A020F0">val</FONT></B> prepend: 'a t * ('b -&gt; 'a) -&gt; 'b t
      <B><FONT COLOR="#A020F0">val</FONT></B> prepare: 'a t * 'a -&gt; Runnable.t
      <B><FONT COLOR="#A020F0">val</FONT></B> switch: ('a t -&gt; Runnable.t) -&gt; 'a
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
<p>
 
</p>
<p>
<tt>MLton.Thread</tt> provides access to MLton's user-level thread implementation (i.e. not OS-level threads).  Threads are lightweight data structures that represent a paused computation.  Runnable threads are threads that will begin or continue computing when <tt>switch</tt>ed to.  <tt>MLton.Thread</tt> does not include a default scheduling mechanism, but it can be used to implement both preemptive and non-preemptive threads. 
</p>

    <ul>

    <li>
<p>
 <tt>type&nbsp;AtomicState.t</tt> 
</p>
</li>

        <ul>

  the type of atomic states. 
        </ul>


    <li class="gap">
<p>
 <tt>atomically&nbsp;f</tt> 
</p>
</li>

        <ul>

  runs <tt>f</tt> in a critical section. 
        </ul>


    <li class="gap">
<p>
 <tt>atomicBegin&nbsp;()</tt> 
</p>
</li>

        <ul>

  begins a critical section. 
        </ul>


    <li class="gap">
<p>
 <tt>atomicEnd&nbsp;()</tt> 
</p>
</li>

        <ul>

  ends a critical section. 
        </ul>


    <li class="gap">
<p>
 <tt>atomicState&nbsp;()</tt> 
</p>
</li>

        <ul>

  returns the current atomic state. 
        </ul>


    <li class="gap">
<p>
 <tt>type&nbsp;Runnable.t</tt> 
</p>
</li>

        <ul>

  the type of threads that can be resumed. 
        </ul>


    <li class="gap">
<p>
 <tt>type&nbsp;'a&nbsp;t</tt> 
</p>
</li>

        <ul>

  the type of threads that expect a value of type <tt>'a</tt>. 
        </ul>


    <li class="gap">
<p>
 <tt>atomicSwitch&nbsp;f</tt> 
</p>
</li>

        <ul>

  like <tt>switch</tt>, but assumes an atomic calling context.  Upon   <tt>switch</tt>ing back to the current thread, an implicit   <tt>atomicEnd</tt> is performed. 
        </ul>


    <li class="gap">
<p>
 <tt>new&nbsp;f</tt> 
</p>
</li>

        <ul>

  creates a new thread that, when run, applies <tt>f</tt> to the value   given to the thread.  <tt>f</tt> must terminate by <tt>switch</tt>ing to   another thread or exiting the process. 
        </ul>


    <li class="gap">
<p>
 <tt>prepend&nbsp;(t,&nbsp;f)</tt> 
</p>
</li>

        <ul>

  creates a new thread (destroying <tt>t</tt> in the process) that first   applies <tt>f</tt> to the value given to the thread and then continues   with <tt>t</tt>.  This is a constant time operation. 
        </ul>


    <li class="gap">
<p>
 <tt>prepare&nbsp;(t,&nbsp;v)</tt> 
</p>
</li>

        <ul>

  prepares a new runnable thread (destroying <tt>t</tt> in the process)   that will evaluate <tt>t</tt> on <tt>v</tt>. 
        </ul>


    <li class="gap">
<p>
 <tt>switch&nbsp;f</tt> 
</p>
</li>

        <ul>

  applies <tt>f</tt> to the current thread to get <tt>rt</tt>, and then start   running thread <tt>rt</tt>.  It is an error for <tt>f</tt> to perform   another <tt>switch</tt>.  <tt>f</tt> is guaranteed to run atomically. 
        </ul>



    </ul>


<h2 id="head-b59f5a84d311ffa9c081e150b9d22e77bb539300">Example of non-preemptive threads</h2>

<pre class=code>
<B><FONT COLOR="#0000FF">structure</FONT></B> Queue:
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> 'a t

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> new: unit -&gt; 'a t
      <B><FONT COLOR="#A020F0">val</FONT></B> enque: 'a t * 'a -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> deque: 'a t -&gt; 'a option
   <B><FONT COLOR="#0000FF">end</FONT></B> =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">datatype</FONT></B><FONT COLOR="#228B22"><B> 'a t </FONT></B>=<FONT COLOR="#228B22"><B> <FONT COLOR="#B8860B">T</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> {front: 'a list ref, back: 'a list ref}

      </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> new() = T{front = ref [], back = ref []}

      <B><FONT COLOR="#A020F0">fun</FONT></B> enque(T{back, ...}, x) = back := x :: !back

      <B><FONT COLOR="#A020F0">fun</FONT></B> deque(T{front, back}) =
         <B><FONT COLOR="#A020F0">case</FONT></B> !front <B><FONT COLOR="#A020F0">of</FONT></B>
            [] =&gt; (<B><FONT COLOR="#A020F0">case</FONT></B> !back <B><FONT COLOR="#A020F0">of</FONT></B>
                      [] =&gt; NONE
                    | l =&gt; <B><FONT COLOR="#A020F0">let</FONT></B> <B><FONT COLOR="#A020F0">val</FONT></B> l = rev l
                           <B><FONT COLOR="#A020F0">in</FONT></B> <B><FONT COLOR="#A020F0">case</FONT></B> l <B><FONT COLOR="#A020F0">of</FONT></B>
                              [] =&gt; <B><FONT COLOR="#A020F0">raise</FONT></B> Fail <FONT COLOR="#BC8F8F"><B>&quot;deque&quot;</FONT></B>
                            | x :: l =&gt; (back := []; front := l; SOME x)
                           <B><FONT COLOR="#A020F0">end</FONT></B>)
          | x :: l =&gt; (front := l; SOME x) 
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#0000FF">structure</FONT></B> Thread:
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">val</FONT></B> exit: unit -&gt; 'a
      <B><FONT COLOR="#A020F0">val</FONT></B> run: unit -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> spawn: (unit -&gt; unit) -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> yield: unit -&gt; unit
   <B><FONT COLOR="#0000FF">end</FONT></B> =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#0000FF">open</FONT></B> MLton
      <B><FONT COLOR="#0000FF">open</FONT></B> Thread

      <B><FONT COLOR="#A020F0">val</FONT></B> topLevel: Thread.Runnable.t option ref = ref NONE

      <B><FONT COLOR="#A020F0">local</FONT></B>
         <B><FONT COLOR="#A020F0">val</FONT></B> threads: Thread.Runnable.t Queue.t = Queue.new()
      <B><FONT COLOR="#A020F0">in</FONT></B>
         <B><FONT COLOR="#A020F0">fun</FONT></B> ready (t: Thread.Runnable.t) : unit = 
            Queue.enque(threads, t)
         <B><FONT COLOR="#A020F0">fun</FONT></B> next () : Thread.Runnable.t =
            <B><FONT COLOR="#A020F0">case</FONT></B> Queue.deque threads <B><FONT COLOR="#A020F0">of</FONT></B>
               NONE =&gt; valOf(!topLevel)
             | SOME t =&gt; t
      <B><FONT COLOR="#A020F0">end</FONT></B>
   
      <B><FONT COLOR="#A020F0">fun</FONT></B> <FONT COLOR="#228B22"><B>'a</FONT></B> exit(): 'a = switch(<B><FONT COLOR="#A020F0">fn</FONT></B> _ =&gt; next())
      
      <B><FONT COLOR="#A020F0">fun</FONT></B> new(f: unit -&gt; unit): Thread.Runnable.t =
         Thread.prepare
         (Thread.new (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; ((f() <B><FONT COLOR="#A020F0">handle</FONT></B> _ =&gt; exit())
                                ; exit())),
          ())
         
      <B><FONT COLOR="#A020F0">fun</FONT></B> schedule t = (ready t; next())

      <B><FONT COLOR="#A020F0">fun</FONT></B> yield(): unit = switch(<B><FONT COLOR="#A020F0">fn</FONT></B> t =&gt; schedule (Thread.prepare (t, ())))

      <B><FONT COLOR="#A020F0">val</FONT></B> spawn = ready o new

      <B><FONT COLOR="#A020F0">fun</FONT></B> run(): unit =
         (switch(<B><FONT COLOR="#A020F0">fn</FONT></B> t =&gt;
                 (topLevel := SOME (Thread.prepare (t, ()))
                  ; next()))
          ; topLevel := NONE)
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> <B><FONT COLOR="#A020F0">rec</FONT></B> loop =
   <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">0</FONT></B> =&gt; ()
    | n =&gt; (print(concat[Int.toString n, <FONT COLOR="#BC8F8F"><B>&quot;\n&quot;</FONT></B>])
            ; Thread.yield()
            ; loop(n - <B><FONT COLOR="#5F9EA0">1</FONT></B>))

<B><FONT COLOR="#A020F0">val</FONT></B> <B><FONT COLOR="#A020F0">rec</FONT></B> loop' =
   <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">0</FONT></B> =&gt; ()
    | n =&gt; (Thread.spawn(<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; loop n); loop'(n - <B><FONT COLOR="#5F9EA0">2</FONT></B>))

<B><FONT COLOR="#A020F0">val</FONT></B> _ = Thread.spawn(<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; loop' <B><FONT COLOR="#5F9EA0">10</FONT></B>)

<B><FONT COLOR="#A020F0">val</FONT></B> _ = Thread.run()

<B><FONT COLOR="#A020F0">val</FONT></B> _ = print <FONT COLOR="#BC8F8F"><B>&quot;success\n&quot;</FONT></B>
</PRE>
<p>
 
</p>
<h2 id="head-5312b6df875ff55a1aac1703500af9a957b9a09a">Example of preemptive threads</h2>

<pre class=code>
<B><FONT COLOR="#0000FF">structure</FONT></B> Queue:
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><FONT COLOR="#228B22"><B> 'a t

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> new: unit -&gt; 'a t
      <B><FONT COLOR="#A020F0">val</FONT></B> enque: 'a t * 'a -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> deque: 'a t -&gt; 'a option
   <B><FONT COLOR="#0000FF">end</FONT></B> =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">datatype</FONT></B><FONT COLOR="#228B22"><B> 'a t </FONT></B>=<FONT COLOR="#228B22"><B> <FONT COLOR="#B8860B">T</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> {front: 'a list ref, back: 'a list ref}

      </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> new () = T {front = ref [], back = ref []}

      <B><FONT COLOR="#A020F0">fun</FONT></B> enque (T {back, ...}, x) = back := x :: !back

      <B><FONT COLOR="#A020F0">fun</FONT></B> deque (T {front, back}) =
         <B><FONT COLOR="#A020F0">case</FONT></B> !front <B><FONT COLOR="#A020F0">of</FONT></B>
            [] =&gt; (<B><FONT COLOR="#A020F0">case</FONT></B> !back <B><FONT COLOR="#A020F0">of</FONT></B>
                      [] =&gt; NONE
                    | l =&gt; <B><FONT COLOR="#A020F0">let</FONT></B> <B><FONT COLOR="#A020F0">val</FONT></B> l = rev l
                           <B><FONT COLOR="#A020F0">in</FONT></B> <B><FONT COLOR="#A020F0">case</FONT></B> l <B><FONT COLOR="#A020F0">of</FONT></B>
                              [] =&gt; <B><FONT COLOR="#A020F0">raise</FONT></B> Fail <FONT COLOR="#BC8F8F"><B>&quot;deque&quot;</FONT></B>
                            | x :: l =&gt; (back := []; front := l; SOME x)
                           <B><FONT COLOR="#A020F0">end</FONT></B>)
          | x :: l =&gt; (front := l; SOME x) 
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#0000FF">structure</FONT></B> Thread:
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">val</FONT></B> exit: unit -&gt; 'a
      <B><FONT COLOR="#A020F0">val</FONT></B> run: unit -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> spawn: (unit -&gt; unit) -&gt; unit
      <B><FONT COLOR="#A020F0">val</FONT></B> yield: unit -&gt; unit
   <B><FONT COLOR="#0000FF">end</FONT></B> =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#0000FF">open</FONT></B> Posix.Signal
      <B><FONT COLOR="#0000FF">open</FONT></B> MLton
      <B><FONT COLOR="#0000FF">open</FONT></B> Itimer Signal Thread

      <B><FONT COLOR="#A020F0">val</FONT></B> topLevel: Thread.Runnable.t option ref = ref NONE

      <B><FONT COLOR="#A020F0">local</FONT></B>
         <B><FONT COLOR="#A020F0">val</FONT></B> threads: Thread.Runnable.t Queue.t = Queue.new ()
      <B><FONT COLOR="#A020F0">in</FONT></B>
         <B><FONT COLOR="#A020F0">fun</FONT></B> ready t = Queue.enque (threads, t)
         <B><FONT COLOR="#A020F0">fun</FONT></B> next () =
            <B><FONT COLOR="#A020F0">case</FONT></B> Queue.deque threads <B><FONT COLOR="#A020F0">of</FONT></B>
               NONE =&gt; valOf (!topLevel)
             | SOME t =&gt; t
      <B><FONT COLOR="#A020F0">end</FONT></B>
   
      <B><FONT COLOR="#A020F0">fun</FONT></B> <FONT COLOR="#228B22"><B>'a</FONT></B> exit (): 'a = switch (<B><FONT COLOR="#A020F0">fn</FONT></B> _ =&gt; next ())
      
      <B><FONT COLOR="#A020F0">fun</FONT></B> new (f: unit -&gt; unit): Thread.Runnable.t =
         Thread.prepare
         (Thread.new (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; ((f () <B><FONT COLOR="#A020F0">handle</FONT></B> _ =&gt; exit ())
                                ; exit ())),
          ())
         
      <B><FONT COLOR="#A020F0">fun</FONT></B> schedule t = (ready t; next ())

      <B><FONT COLOR="#A020F0">fun</FONT></B> yield (): unit = switch (<B><FONT COLOR="#A020F0">fn</FONT></B> t =&gt; schedule (Thread.prepare (t, ())))

      <B><FONT COLOR="#A020F0">val</FONT></B> spawn = ready o new

      <B><FONT COLOR="#A020F0">fun</FONT></B> setItimer t =
         Itimer.set (Itimer.Real,
                     {value = t,
                      interval = t})

      <B><FONT COLOR="#A020F0">fun</FONT></B> run (): unit =
         (switch (<B><FONT COLOR="#A020F0">fn</FONT></B> t =&gt;
                  (topLevel := SOME (Thread.prepare (t, ()))
                   ; new (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; (setHandler (alrm, Handler.handler schedule)
                                    ; setItimer (Time.fromMilliseconds <B><FONT COLOR="#5F9EA0">20</FONT></B>)))))
          ; setItimer Time.zeroTime
          ; ignore alrm
          ; topLevel := NONE)
   <B><FONT COLOR="#0000FF">end</FONT></B>

<B><FONT COLOR="#A020F0">val</FONT></B> <B><FONT COLOR="#A020F0">rec</FONT></B> delay =
   <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">0</FONT></B> =&gt; ()
    | n =&gt; delay (n - <B><FONT COLOR="#5F9EA0">1</FONT></B>)
         
<B><FONT COLOR="#A020F0">val</FONT></B> <B><FONT COLOR="#A020F0">rec</FONT></B> loop =
   <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">0</FONT></B> =&gt; ()
    | n =&gt; (delay <B><FONT COLOR="#5F9EA0">500000</FONT></B>; loop (n - <B><FONT COLOR="#5F9EA0">1</FONT></B>))

<B><FONT COLOR="#A020F0">val</FONT></B> <B><FONT COLOR="#A020F0">rec</FONT></B> loop' =
   <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">0</FONT></B> =&gt; ()
    | n =&gt; (Thread.spawn (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; loop n); loop' (n - <B><FONT COLOR="#5F9EA0">1</FONT></B>))

<B><FONT COLOR="#A020F0">val</FONT></B> _ = Thread.spawn (<B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; loop' <B><FONT COLOR="#5F9EA0">10</FONT></B>)

<B><FONT COLOR="#A020F0">val</FONT></B> _ = Thread.run ()

<B><FONT COLOR="#A020F0">val</FONT></B> _ = print <FONT COLOR="#BC8F8F"><B>&quot;success\n&quot;</FONT></B>
</PRE>
<p>
 
</p>
</div>



<p>
<hr>
Last edited on 2005-12-02 03:52:11 by <span title="209-6-203-188.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com"><a href="MatthewFluet">MatthewFluet</a></span>.
</body></html>
