logo

const class

sys::Thread

sys::Obj
  sys::Thread
   1  //
   2  // Copyright (c) 2006, Brian Frank and Andy Frank
   3  // Licensed under the Academic Free License version 3.0
   4  //
   5  // History:
   6  //   26 Dec 06  Brian Frank  Stub
   7  //   28 Jan 07  Brian Frank  Implement threading model
   8  //
   9  
  10  **
  11  ** Thread models a thread of execution within a process.
  12  ** See `docLang::Threading` for details.
  13  **
  14  const class Thread
  15  {
  16  
  17  //////////////////////////////////////////////////////////////////////////
  18  // Construction
  19  //////////////////////////////////////////////////////////////////////////
  20  
  21    **
  22    ** Make a new thread with the given name.  If name is non-null then it
  23    ** must not conflict with any threads currently active (new or running)
  24    ** otherwise ArgErr is thrown.  Convention is to use a dotted notation
  25    ** beginning with your pod name to avoid naming collisions.  If name is
  26    ** null, then a unique name is automatically generated.  If name is
  27    ** non-null, then it must be valid according to `Uri.isName` otherwise
  28    ** NameErr is thrown.
  29    **
  30    ** If run is non-null, then it is invoked as the main loop of the thread.
  31    ** If run is specified then it must be an immutable function (it cannot
  32    ** capture state from the calling thread), otherwise NotImmutableErr is
  33    ** thrown.  If run is null, then you must subclass Thread and override
  34    ** the run() method.  The return value of run is available to the first
  35    ** thread which calls `join`.
  36    **
  37    ** The thread is created in the new state, and must be started using
  38    ** the start method.
  39    **
  40    new make(Str name := null, |Thread t->Obj| run := null)
  41  
  42  //////////////////////////////////////////////////////////////////////////
  43  // Management
  44  //////////////////////////////////////////////////////////////////////////
  45  
  46    **
  47    ** Lookup a thread in this VM by name.  If the thread doesn't
  48    ** exist and checked is false then return null, otherwise throw
  49    ** UnknownThreadErr.  Only active threads which are in the new
  50    ** or running state may be found by name.
  51    **
  52    static Thread find(Str name, Bool checked := true)
  53  
  54    **
  55    ** Get the list of all active (new or running) threads
  56    ** in the VM.
  57    **
  58    static Thread[] list()
  59  
  60    **
  61    ** Get the currently executing thread.  Throw Err if
  62    ** the current thread is not a proper Fan thread.
  63    **
  64    static Thread current()
  65  
  66    **
  67    ** Return the map of thread local variables.  This is a map of "global"
  68    ** variables visible only to the current thread.  These variables are
  69    ** keyed by a string name - by convention use a dotted notation beginning
  70    ** with your pod name to avoid naming collisions.
  71    **
  72    static Str:Obj locals()
  73  
  74  //////////////////////////////////////////////////////////////////////////
  75  // Identity
  76  //////////////////////////////////////////////////////////////////////////
  77  
  78    **
  79    ** Get the name of this thread which uniquely
  80    ** identifies this thread within the VM.
  81    **
  82    Str name()
  83  
  84    **
  85    ** Print this thread's stack trace to the specified output
  86    ** stream (or Sys.out by default).  If this thread is not currently
  87    ** running print nothing.
  88    **
  89    Void trace(OutStream out := Sys.out)
  90  
  91    **
  92    ** Return true if same thread according '===' same operator.
  93    **
  94    override Bool equals(Obj obj)
  95  
  96    **
  97    ** Return name.hash.
  98    **
  99    override Int hash()
 100  
 101    **
 102    ** Default toStr returns name.
 103    **
 104    override Str toStr()
 105  
 106  //////////////////////////////////////////////////////////////////////////
 107  // State
 108  //////////////////////////////////////////////////////////////////////////
 109  
 110    **
 111    ** Return if this thread has been created, but not yet started.
 112    **
 113    Bool isNew()
 114  
 115    **
 116    ** Return if this thread has been started, but not yet stopped.
 117    **
 118    Bool isRunning()
 119  
 120    **
 121    ** Return if this thread has been stopped.
 122    **
 123    Bool isDead()
 124  
 125  //////////////////////////////////////////////////////////////////////////
 126  // Lifecycle
 127  //////////////////////////////////////////////////////////////////////////
 128  
 129    **
 130    ** Start this thread running.  If the thread is already
 131    ** running or has been stopped, then throw Err.  Return this.
 132    **
 133    Thread start()
 134  
 135    **
 136    ** Stop this thread from running.  If this thread
 137    ** is not currently running, then this method does nothing.
 138    ** Note that the thread likely doesn't actually terminate
 139    ** until it reaches an interruptable point in its main loop.
 140    **
 141    Void stop()
 142  
 143    **
 144    ** Wait for this thread to stop.  If timeout is non-null,
 145    ** then wait no longer then specified timeout.  If this thread
 146    ** hasn't been started yet, then throw Err.  If this thread
 147    ** is already dead, then this method is a no op.  Return
 148    ** the result of the run method for the first thread to join,
 149    ** or null on subsequent calls.
 150    **
 151    Obj join(Duration timeout := null)
 152  
 153    **
 154    ** Put the currently executing thread to sleep for the
 155    ** specified period.  If the thread is interrupted for any
 156    ** reason while sleeping, then InterruptedErr is thrown.
 157    **
 158    static Void sleep(Duration duration)
 159  
 160    **
 161    ** The run method implements the code to run in the thread.
 162    ** If a run function was specified in the constructor, then it
 163    ** is invoked, otherwise subclasses should override this method.
 164    ** Threads which wish to process their message queue must
 165    ** enter the main loop by calling the loop() method.  The
 166    ** return value of this method is available to the first thread
 167    ** which calls the join method (the result is not required to
 168    ** be immutable).
 169    **
 170    protected virtual Obj run()
 171  
 172    **
 173    ** Enter the message loop.  This method does not return until
 174    ** the thread is stopped.  This receive callback is invoked by
 175    ** the main loop each time a message is received from its send queue.
 176    ** The callback should process the message and return a response.
 177    ** If the calling thread is not this thread, then throw Err.
 178    **
 179    ** If the the message was enqueued by sendAsync the response is
 180    ** ignored; exceptions are printed to standard output and ignored.
 181    **
 182    ** If the message was enqueued by sendSync the response is
 183    ** returned to the caller and must be immutable or serializable;
 184    ** exceptions are raised to the caller.
 185    **
 186    Void loop(|Obj msg->Obj| receive)
 187  
 188  //////////////////////////////////////////////////////////////////////////
 189  // Messaging
 190  //////////////////////////////////////////////////////////////////////////
 191  
 192    **
 193    ** Enqueue the specified message for this thread, then
 194    ** block the calling thread until this thread processes the
 195    ** message via the loop() callback and return the result.
 196    ** If the loop() callback throws an exception processing
 197    ** the message, then that exception is raised to the calling
 198    ** thread.  If msg is not immutable or serializable, then IOErr
 199    ** is thrown.  If this thread is stopped while the caller is
 200    ** blocked, then an InterruptedErr is thrown.  Note that flow
 201    ** control may block the caller until there is enough
 202    ** space in this thread's message queue.
 203    **
 204    Obj sendSync(Obj msg)
 205  
 206    **
 207    ** Enqueue the specified message for this thread to process in
 208    ** its received() callback.  Using sendAsync() is fire-and-forget,
 209    ** the caller has no guarantee that this thread will successfully
 210    ** process the message.  If msg is not immutable or serializable,
 211    ** then IOErr is thrown.  Note that flow control may block the
 212    ** caller until there is enough space in this thread's message
 213    ** queue.
 214    **
 215    Void sendAsync(Obj msg)
 216  
 217  }