Provided by: tcl-thread_2.8.2-1_amd64 bug

NAME

       thread - Extension for script access to Tcl threading

SYNOPSIS

       package require Tcl  8.4

       package require Thread  ?2.8?

       thread::create ?-joinable? ?-preserved? ?script?

       thread::preserve ?id?

       thread::release ?-wait? ?id?

       thread::id

       thread::errorproc ?procname?

       thread::cancel ?-unwind? id ?result?

       thread::unwind

       thread::exit ?status?

       thread::names

       thread::exists id

       thread::send ?-async? ?-head? id script ?varname?

       thread::broadcast script

       thread::wait

       thread::eval ?-lock mutex? arg ?arg ...?

       thread::join id

       thread::configure id ?option? ?value? ?...?

       thread::transfer id channel

       thread::detach channel

       thread::attach channel

       thread::mutex

       thread::mutex create ?-recursive?

       thread::mutex destroy mutex

       thread::mutex lock mutex

       thread::mutex unlock mutex

       thread::rwmutex

       thread::rwmutex create

       thread::rwmutex destroy mutex

       thread::rwmutex rlock mutex

       thread::rwmutex wlock mutex

       thread::rwmutex unlock mutex

       thread::cond

       thread::cond create

       thread::cond destroy cond

       thread::cond notify cond

       thread::cond wait cond mutex ?ms?

________________________________________________________________________________________________________________

DESCRIPTION

       The thread extension creates threads that contain Tcl interpreters, and it lets you send scripts to those
       threads for evaluation.  Additionaly, it provides script-level access  to  basic  thread  synchronization
       primitives, like mutexes and condition variables.

COMMANDS

       This  section  describes  commands for creating and destroying threads and sending scripts to threads for
       evaluation.

       thread::create ?-joinable? ?-preserved? ?script?
              This command creates a thread that  contains  a  Tcl  interpreter.   The  Tcl  interpreter  either
              evaluates the optional script, if specified, or it waits in the event loop for scripts that arrive
              via the thread::send command. The result, if any, of the optional script is never returned to  the
              caller.   The  result  of  thread::create is the ID of the thread. This is the opaque handle which
              identifies the newly created thread for all other package commands. The handle of the thread  goes
              out of scope automatically when thread is marked for exit (see the thread::release command below).

              If  the  optional script argument contains the thread::wait command the thread will enter into the
              event loop. If such command is not found  in the script the thread will run the script to the  end
              and  exit.  In  that case, the handle may be safely ignored since it refers to a thread which does
              not exists any more at the time when the command returns.

              Using flag -joinable it is possible to create a joinable thread, i.e. one upon whose exit  can  be
              waited  upon  by  using  thread::join  command.   Note  that failure to join a thread created with
              -joinable flag results in resource and memory leaks.

              Threads created by the thread::create cannot be destroyed forcefully. Consequently,  there  is  no
              corresponding  thread destroy command. A thread may only be released using the thread::release and
              if its internal reference count drops to zero, the thread is  marked  for  exit.  This  kicks  the
              thread  out of the event loop servicing and the thread continues to execute commands passed in the
              script argument, following the thread::wait command. If this was the last command in  the  script,
              as usualy the case, the thread will exit.

              It  is  possible  to create a situation in which it may be impossible to terminate the thread, for
              example by putting some endless loop after the thread::wait or entering the event  loop  again  by
              doing an vwait-type of command. In such cases, the thread may never exit. This is considered to be
              a bad practice and should be avoided if possible. This is best illustrated by the example below:

                  # You should never do ...
                  set tid [thread::create {
                      package require Http
                      thread::wait
                      vwait forever ; # <-- this!
                  }]

              The thread created in the above example will never be able to exit.  After it  has  been  released
              with  the  last  matching  thread::release  call, the thread will jump out of the thread::wait and
              continue to execute commands following. It will enter vwait command and wait endlessly for events.
              There is no way one can terminate such thread, so you wouldn't want to do this!

              Each newly created has its internal reference counter set to 0 (zero), i.e. it is unreserved. This
              counter  gets  incremented  by  a  call  to  thread::preserve  and  decremented  by  a   call   to
              thread::release  command.  These  two  commands  implement simple but effective thread reservation
              system and offer predictable and controllable  thread  termination  capabilities.  It  is  however
              possible  to  create  initialy  preserved  threads  by using flag -preserved of the thread::create
              command. Threads created with this flag have the initial value  of  the  reference  counter  of  1
              (one), and are thus initially marked reserved.

       thread::preserve ?id?
              This  command  increments  the  thread reference counter. Each call to this command increments the
              reference counter by one (1).  Command returns the  value  of  the  reference  counter  after  the
              increment.   If  called  with  the  optional  thread  id,  the command preserves the given thread.
              Otherwise the current thread is preserved.

              With reference counting,  one  can  implement  controlled  access  to  a  shared  Tcl  thread.  By
              incrementing the reference counter, the caller signalizes that he/she wishes to use the thread for
              a longer period of time. By decrementing the counter, caller signalizes that he/she  has  finished
              using the thread.

       thread::release ?-wait? ?id?
              This  command  decrements  the  thread reference counter. Each call to this command decrements the
              reference counter by one (1).  If called with the optional thread id,  the  command  releases  the
              given  thread.  Otherwise,  the  current  thread  is  released.   Command returns the value of the
              reference counter after the decrement.  When the reference counter reaches zero  (0),  the  target
              thread  is  marked  for termination. You should not reference the thread after the thread::release
              command returns zero or negative integer.  The handle of the thread goes out of scope  and  should
              not be used any more. Any following reference to the same thread handle will result in Tcl error.

              Optional  flag  -wait  instructs  the  caller thread to wait for the target thread to exit, if the
              effect of the command would result in termination of the target thread, i.e. if the return  result
              would  be  zero  (0).  Without  the flag, the caller thread does not wait for the target thread to
              exit. Care must  be  taken  when  using  the  -wait,  since  this  may  block  the  caller  thread
              indefinitely.   This  option  has  been  implemented for some special uses of the extension and is
              deprecated for regular use. Regular users should create joinable threads by  using  the  -joinable
              option of the thread::create command and the thread::join to wait for thread to exit.

       thread::id
              This command returns the ID of the current thread.

       thread::errorproc ?procname?
              This command sets a handler for errors that occur in scripts sent asynchronously, using the -async
              flag of the thread::send command, to other threads.  If  no  handler  is  specified,  the  current
              handler  is  returned.  The  empty  string  resets the handler to default (unspecified) value.  An
              uncaught error in a thread causes an error message to be sent to the standard error channel.  This
              default  reporting  scheme can be changed by registering a procedure which is called to report the
              error. The procname is called in the interpreter that invoked the thread::errorproc  command.  The
              procname is called like this:

                  myerrorproc thread_id errorInfo

       thread::cancel ?-unwind? id ?result?
              This command requires Tcl version 8.6 or higher.

              Cancels  the  script  being evaluated in the thread given by the id parameter. Without the -unwind
              switch the evaluation stack for the interpreter is unwound until an  enclosing  catch  command  is
              found  or  there  are  no  further invocations of the interpreter left on the call stack. With the
              -unwind switch the evaluation  stack  for  the  interpreter  is  unwound  without  regard  to  any
              intervening  catch  command  until there are no further invocations of the interpreter left on the
              call stack. If result is present, it will be used  as  the  error  message  string;  otherwise,  a
              default error message string will be used.

       thread::unwind
              Use of this command is deprecated in favour of more advanced thread reservation system implemented
              with thread::preserve and  thread::release  commands.  Support  for  thread::unwind  command  will
              dissapear in some future major release of the extension.

              This  command  stops a prior thread::wait command. Execution of the script passed to newly created
              thread will continue from the thread::wait command. If thread::wait was the last  command  in  the
              script,  the thread will exit. The command returns empty result but may trigger Tcl error with the
              message "target thread died" in some situations.

       thread::exit ?status?
              Use of this command is deprecated in favour of more advanced thread reservation system implemented
              with  thread::preserve  and  thread::release  commands.  Support  for  thread::exit  command  will
              dissapear in some future major release of the extension.

              This command forces a thread stuck  in  the  thread::wait  command  to  unconditionaly  exit.  The
              thread's  exit status defaults to 666 and can be specified using the optional status argument. The
              execution of thread::exit command is guaranteed to leave the program memory  in  the  unconsistent
              state,  produce  memory  leaks and otherwise affect other subsytem(s) of the Tcl application in an
              unpredictable manner. The command returns empty result but may trigger Tcl error with the  message
              "target thread died" in some situations.

       thread::names
              This  command  returns a list of thread IDs. These are only for threads that have been created via
              thread::create command.  If your application creates other threads at the C level,  they  are  not
              reported by this command.

       thread::exists id
              Returns  true  (1)  if  thread given by the id parameter exists, false (0) otherwise. This applies
              only for threads that have been created via thread::create command.

       thread::send ?-async? ?-head? id script ?varname?
              This command passes a script to another thread and, optionally,  waits  for  the  result.  If  the
              -async  flag  is  specified, the command does not wait for the result and it returns empty string.
              The target thread must enter it's event loop in order to receive scripts sent  via  this  command.
              This  is done by default for threads created without a startup script. Threads can enter the event
              loop explicitly by calling thread::wait or any other relevant Tcl/Tk command, like update,  vwait,
              etc.

              Optional  varname  specifies  name  of the variable to store the result of the script. Without the
              -async flag, the command returns the  evaluation  code,  similarily  to  the  standard  Tcl  catch
              command. If, however, the -async flag is specified, the command returns immediately and caller can
              later vwait on ?varname? to get the result of the passed script

                  set t1 [thread::create]
                  set t2 [thread::create]
                  thread::send -async $t1 "set a 1" result
                  thread::send -async $t2 "set b 2" result
                  for {set i 0} {$i < 2} {incr i} {
                      vwait result
                  }

              In the above example, two threads were fed work and both of them were instructed to signalize  the
              same variable "result" in the calling thread.  The caller entered the event loop twice to get both
              results. Note, however, that the order of the received results may vary, depending on the  current
              system load, type of work done, etc, etc.

              Many  threads  can simultaneously send scripts to the target thread for execution. All of them are
              entered into the event queue of the target thread and executed on  the  FIFO  basis,  intermingled
              with  optional  other  events pending in the event queue of the target thread.  Using the optional
              ?-head? switch, scripts posted to the thread's event queue can be placed on the head,  instead  on
              the tail of the queue, thus being executed in the LIFO fashion.

       thread::broadcast script
              This command passes a script to all threads created by the package for execution. It does not wait
              for response from any of the threads.

       thread::wait
              This enters the event loop so a thread can receive messages from the  thread::send  command.  This
              command  should only be used within the script passed to the thread::create. It should be the very
              last command in the script. If this is not the case, the exiting thread  will  continue  executing
              the script lines past the thread::wait which is usually not what you want and/or expect.

                  set t1 [thread::create {
                      #
                      # Do some initialization work here
                      #
                      thread::wait ; # Enter the event loop
                  }]

       thread::eval ?-lock mutex? arg ?arg ...?
              This  command  concatenates  passed  arguments  and evaluates the resulting script under the mutex
              protection. If no mutex is specified by using the ?-lock mutex? optional  argument,  the  internal
              static mutex is used.

       thread::join id
              This  command waits for the thread with ID id to exit and then returns it's exit code. Errors will
              be returned for threads which are not joinable or already waited upon by another thread.  Upon the
              join the handle of the thread has gone out of scope and should not be used any more.

       thread::configure id ?option? ?value? ?...?
              This  command  configures various low-level aspects of the thread with ID id in the similar way as
              the standard Tcl command  fconfigure  configures  some  Tcl  channel  options.  Options  currently
              supported are: -eventmark and -unwindonerror.

              The  -eventmark option, when set, limits the number of asynchronously posted scripts to the thread
              event loop.  The thread::send -async command will block until the number of pending scripts in the
              event  loop  does  not  drop  below  the  value  configured with -eventmark. Default value for the
              -eventmark is 0 (zero) which effectively disables the checking, i.e. allows for  unlimited  number
              of posted scripts.

              The  -unwindonerror  option,  when  set,  causes  the target thread to unwind if the result of the
              script processing resulted in error. Default value for  the  -unwindonerror  is  0  (false),  i.e.
              thread continues to process scripts after one of the posted scripts fails.

       thread::transfer id channel
              This  moves  the specified channel from the current thread and interpreter to the main interpreter
              of the thread with the given id. After the move the current  interpreter  has  no  access  to  the
              channel  any  more,  but the main interpreter of the target thread will be able to use it from now
              on.  The command waits until the other thread has incorporated the channel. Because of this it  is
              possible  to  deadlock  the  participating  threads  by commanding the other through a synchronous
              thread::send to transfer a channel to us.  This  easily  extends  into  longer  loops  of  threads
              waiting  for  each  other.  Other  restrictions:  the channel in question must not be shared among
              multiple interpreters running in the sending  thread.  This  automatically  excludes  the  special
              channels for standard input, output and error.

              Due  to  the internal Tcl core implementation and the restriction on transferring shared channels,
              one has to take extra  measures  when  transferring  socket  channels  created  by  accepting  the
              connection out of the socket commands callback procedures:

                  socket -server _Accept 2200
                  proc _Accept {s ipaddr port} {
                      after idle [list Accept $s $ipaddr $port]
                  }
                  proc Accept {s ipaddr port} {
                      set tid [thread::create]
                      thread::transfer $tid $s
                  }

       thread::detach channel
              This  detaches  the  specified  channel  from  the current thread and interpreter. After that, the
              current interpreter has no access to the channel any more. The channel  is  in  the  parked  state
              until   some  other  (or  the  same)  thread  attaches  the  channel  again  with  thread::attach.
              Restrictions: same as for transferring shared channels with the thread::transfer command.

       thread::attach channel
              This attaches the previously detached channel  in  the  current  thread/interpreter.  For  already
              existing  channels,  the  command does nothing, i.e. it is not an error to attach the same channel
              more than once. The first operation will actualy  perform  the  operation,  while  all  subsequent
              operation will just do nothing. Command throws error if the channel cannot be found in the list of
              detached channels and/or in the current interpreter.

       thread::mutex
              Mutexes are most common thread synchronization primitives.  They are used  to  synchronize  access
              from  two  or  more  threads  to  one or more shared resources. This command provides script-level
              access to exclusive and/or recursive mutexes. Exclusive mutexes can be locked  only  once  by  one
              thread,  while  recursive  mutexes  can  be  locked  many  times by the same thread. For recursive
              mutexes, number of lock and unlock operations must match,  otherwise,  the  mutex  will  never  be
              released, which would lead to various deadlock situations.

              Care has to be taken when using mutexes in an multithreading program.  Improper use of mutexes may
              lead to various deadlock situations, especially when using exclusive mutexes.

              The thread::mutex command supports following subcommands and options:

              thread::mutex create ?-recursive?
                     Creates the mutex and returns it's opaque handle. This handle should be used for any future
                     reference  to the newly created mutex.  If no optional ?-recursive? argument was specified,
                     the command creates the exclusive  mutex.  With  the  ?-recursive?  argument,  the  command
                     creates a recursive mutex.

              thread::mutex destroy mutex
                     Destroys  the  mutex.  Mutex should be in unlocked state before the destroy attempt. If the
                     mutex is locked, the command will throw Tcl error.

              thread::mutex lock mutex
                     Locks the mutex. Locking the exclusive mutex may throw Tcl error if on attempt to lock  the
                     same  mutex  twice  from the same thread. If your program logic forces you to lock the same
                     mutex twice or  more  from  the  same  thread  (this  may  happen  in  recursive  procedure
                     invocations) you should consider using the recursive mutexes.

              thread::mutex unlock mutex
                     Unlocks  the  mutex  so some other thread may lock it again.  Attempt to unlock the already
                     unlocked mutex will throw Tcl error.

       thread::rwmutex
              This command creates  many-readers/single-writer  mutexes.  Reader/writer  mutexes  allow  you  to
              serialize  access to a shared resource more optimally.  In situations where a shared resource gets
              mostly read and seldom modified, you might gain some performace  by  using  reader/writer  mutexes
              instead of exclusive or recursive mutexes.

              For  reading  the  resource,  thread should obtain a read lock on the resource.  Read lock is non-
              exclusive, meaning that more than one thread can obtain a read lock to the same resource,  without
              waiting  on  other  readers.  For changing the resource, however, a thread must obtain a exclusive
              write lock. This lock effectively blocks all threads from gaining the read-lock while the resource
              is  been modified by the writer thread.  Only after the write lock has been released, the resource
              may be read-locked again.

              The thread::rwmutex command supports following subcommands and options:

              thread::rwmutex create
                     Creates the reader/writer mutex and returns it's opaque handle.  This handle should be used
                     for any future reference to the newly created mutex.

              thread::rwmutex destroy mutex
                     Destroys  the  reader/writer  mutex.  If the mutex is already locked, attempt to destroy it
                     will throw Tcl error.

              thread::rwmutex rlock mutex
                     Locks the mutex for reading. More than one thread may read-lock the same mutex at the  same
                     time.

              thread::rwmutex wlock mutex
                     Locks  the  mutex  for  writing.  Only one thread may write-lock the same mutex at the same
                     time. Attempt to write-lock same mutex twice from the same thread will throw Tcl error.

              thread::rwmutex unlock mutex
                     Unlocks the mutex so some other thread may  lock  it  again.   Attempt  to  unlock  already
                     unlocked mutex will throw Tcl error.

       thread::cond
              This  command provides script-level access to condition variables.  A condition variable creates a
              safe environment for the program to test some condition, sleep on it when false  and  be  awakened
              when  it  might  have  become  true. A condition variable is always used in the conjuction with an
              exclusive mutex. If you attempt to use other type  of  mutex  in  conjuction  with  the  condition
              variable, a Tcl error will be thrown.

              The command supports following subcommands and options:

              thread::cond create
                     Creates  the condition variable and returns it's opaque handle.  This handle should be used
                     for any future reference to newly created condition variable.

              thread::cond destroy cond
                     Destroys condition variable cond. Extreme care has to be taken that nobody is  using  (i.e.
                     waiting on) the condition variable, otherwise unexpected errors may happen.

              thread::cond notify cond
                     Wakes up all threads waiting on the condition variable cond.

              thread::cond wait cond mutex ?ms?
                     This  command  is  used  to suspend program execution until the condition variable cond has
                     been signalled or the optional timer has expired.  The exclusive mutex must  be  locked  by
                     the  calling  thread  on entrance to this command. If the mutex is not locked, Tcl error is
                     thrown.  While waiting on the cond, the command releases mutex.  Before  returning  to  the
                     calling thread, the command re-acquires the mutex again. Unlocking the mutex and waiting on
                     the condition variable cond is done atomically.

                     The ms  command  option,  if  given,  must  be  an  integer  specifying  time  interval  in
                     milliseconds  the  command waits to be signalled.  Otherwise the command waits on condition
                     notify forever.

                     In multithreading programs, there are many situations where a thread has to wait  for  some
                     event to happen until it is allowed to proceed.  This is usually accomplished by repeatedly
                     testing a condition under the mutex protection and waiting on the condition variable  until
                     the condition evaluates to true:

                         set mutex [thread::mutex create]
                         set cond  [thread::cond  create]

                         thread::mutex lock $mutex
                         while {<some_condition_is_true>} {
                             thread::cond wait $cond $mutex
                         }
                         # Do some work under mutex protection
                         thread::mutex unlock $mutex

                     Repeated  testing of the condition is needed since the condition variable may get signalled
                     without the condition being actually changed (spurious thread wake-ups, for example).

DISCUSSION

       The fundamental threading model in Tcl is that there can be one or more Tcl interpreters per thread,  but
       each  Tcl  interpreter  should  only  be  used  by  a  single thread which created it.  A "shared memory"
       abstraction is awkward to provide in Tcl because Tcl makes assumptions about variable and data ownership.
       Therefore  this  extension  supports  a simple form of threading where the main thread can manage several
       background, or "worker" threads.  For example,  an  event-driven  server  can  pass  requests  to  worker
       threads, and then await responses from worker threads or new client requests. Everything goes through the
       common Tcl event loop, so message passing between threads works naturally with event-driven I/O, vwait on
       variables, and so forth. For the transfer of bulk information it is possible to move channels between the
       threads.

       For advanced multithreading scripts, script-level access to two basic synchronization  primitives,  mutex
       and condition variables, is also supported.

SEE ALSO

       http://www.tcl.tk/doc/howto/thread_model.html, tpool, tsv, ttrace

KEYWORDS

       events, message passing, mutex, synchronization, thread