Provided by: tcl-thread_2.8.8-2_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.  Additionally, 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. Both of them would take place
              simultaneously  with  the  return  of  command thread::create to the caller thread.
              Neither the caller is waiting for the finishing of optional script, nor the result,
              if  any,  of the script is 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
              usually 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
              initially 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  disappear  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 disappear in some future major release of the extension.

              This  command  forces a thread stuck in the thread::wait command to unconditionally
              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  inconsistent  state,  produce  memory  leaks  and
              otherwise  affect  other  subsystem(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, similarly 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.

              When -eventmark is provided with a value greater than 0 (zero), that value  is  the
              maximum number of asynchronously posted scripts that may be pending for the thread.
              thread::send -async blocks until the number of pending scripts in  the  event  loop
              drops below the -eventmark value.

              When  -unwindonerror  is provided with a value of true, an error result in a script
              causes the thread to unwind, making it unavailable to evaluate additional scripts.

       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 actually 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
              performance  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 conjunction with an exclusive mutex. If you attempt
              to use other type of mutex in conjunction 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