Tcl package Thread source code

Check-in [8ee9e53308]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge trunk. Remove badoctal test, which no longer makes sense with Tcl 9.0
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | novem
Files: files | file ages | folders
SHA3-256: 8ee9e53308debb4c189d4c2e3c9c3b6e8e87e15e3febcd802339aa2416301aa8
User & Date: jan.nijtmans 2018-10-12 18:44:36
Context
2018-10-12
18:50
Merge trunk check-in: 93cca4133e user: jan.nijtmans tags: novem
18:44
Merge trunk. Remove badoctal test, which no longer makes sense with Tcl 9.0 check-in: 8ee9e53308 user: jan.nijtmans tags: novem
18:41
merge-mark check-in: e8dcabfdf7 user: jan.nijtmans tags: trunk
2018-02-26
22:59
Merge trunk check-in: 7b198e45f6 user: jan.nijtmans tags: novem
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to configure.

  2111   2111       # If the user did not set CFLAGS, set it now to keep macros
  2112   2112       # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
  2113   2113       if test "${CFLAGS+set}" != "set" ; then
  2114   2114   	CFLAGS=""
  2115   2115       fi
  2116   2116   
  2117   2117       case "`uname -s`" in
  2118         -	*win32*|*WIN32*|*MINGW32_*)
         2118  +	*win32*|*WIN32*|*MINGW32_*|*MINGW64_*)
  2119   2119   	    # Extract the first word of "cygpath", so it can be a program name with args.
  2120   2120   set dummy cygpath; ac_word=$2
  2121   2121   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
  2122   2122   $as_echo_n "checking for $ac_word... " >&6; }
  2123   2123   if ${ac_cv_prog_CYGPATH+:} false; then :
  2124   2124     $as_echo_n "(cached) " >&6
  2125   2125   else
................................................................................
  2387   2387   	    fi
  2388   2388   
  2389   2389   	    # check in a few common install locations
  2390   2390   	    if test x"${ac_cv_c_tclconfig}" = x ; then
  2391   2391   		for i in `ls -d ${libdir} 2>/dev/null` \
  2392   2392   			`ls -d ${exec_prefix}/lib 2>/dev/null` \
  2393   2393   			`ls -d ${prefix}/lib 2>/dev/null` \
  2394         -			`ls -d /usr/contrib/lib 2>/dev/null` \
  2395   2394   			`ls -d /usr/local/lib 2>/dev/null` \
         2395  +			`ls -d /usr/contrib/lib 2>/dev/null` \
  2396   2396   			`ls -d /usr/pkg/lib 2>/dev/null` \
  2397   2397   			`ls -d /usr/lib 2>/dev/null` \
  2398   2398   			`ls -d /usr/lib64 2>/dev/null` \
  2399   2399   			`ls -d /usr/lib/tcl8.6 2>/dev/null` \
  2400   2400   			`ls -d /usr/lib/tcl8.5 2>/dev/null` \
         2401  +			`ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
         2402  +			`ls -d /usr/local/lib/tcl8.5 2>/dev/null` \
         2403  +			`ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
         2404  +			`ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \
  2401   2405   			; do
  2402   2406   		    if test -f "$i/tclConfig.sh" ; then
  2403   2407   			ac_cv_c_tclconfig="`(cd $i; pwd)`"
  2404   2408   			break
  2405   2409   		    fi
  2406   2410   		done
  2407   2411   	    fi
................................................................................
  7639   7643       # standard manufacturer compiler.
  7640   7644   
  7641   7645       if test "$GCC" = yes; then :
  7642   7646   
  7643   7647   	case $system in
  7644   7648   	    AIX-*) ;;
  7645   7649   	    BSD/OS*) ;;
  7646         -	    CYGWIN_*|MINGW32_*) ;;
         7650  +	    CYGWIN_*|MINGW32_*|MINGW64_*) ;;
  7647   7651   	    IRIX*) ;;
  7648   7652   	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
  7649   7653   	    Darwin-*) ;;
  7650   7654   	    SCO_SV-3.2*) ;;
  7651   7655   	    windows) ;;
  7652   7656   	    *) SHLIB_CFLAGS="-fPIC" ;;
  7653   7657   	esac

Changes to doc/html/thread.html.

     1      1   
     2         -<html><head>
            2  +<!DOCTYPE html><html><head>
     3      3   <title>thread - Tcl Threading</title>
     4      4   <style type="text/css"><!--
     5      5       HTML {
     6      6   	background: 	#FFFFFF;
     7      7   	color: 		black;
     8      8       }
     9      9       BODY {
................................................................................
    88     88       }
    89     89       UL.doctools_requirements {
    90     90   	margin-bottom: 	1em;
    91     91   	border-bottom:	1px solid black;
    92     92       }
    93     93   --></style>
    94     94   </head>
    95         -<! -- Generated from file '' by tcllib/doctools with format 'html'
           95  +<!-- Generated from file '' by tcllib/doctools with format 'html'
    96     96      -->
    97         -<! -- thread.n
           97  +<!-- thread.n
    98     98      -->
    99     99   <body><div class="doctools">
   100    100   <h1 class="doctools_title">thread(n) 2.8  &quot;Tcl Threading&quot;</h1>
   101    101   <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
   102    102   <p>thread - Extension for script access to Tcl threading</p>
   103    103   </div>
   104    104   <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
................................................................................
   157    157   </ul>
   158    158   </div>
   159    159   </div>
   160    160   <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
   161    161   <p>The <b class="package">thread</b> extension creates threads that contain Tcl
   162    162   interpreters, and it lets you send scripts to those threads for
   163    163   evaluation.
   164         -Additionaly, it provides script-level access to basic thread
          164  +Additionally, it provides script-level access to basic thread
   165    165   synchronization primitives, like mutexes and condition variables.</p>
   166    166   </div>
   167    167   <div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2>
   168    168   <p>This section describes commands for creating and destroying threads
   169    169   and sending scripts to threads for evaluation.</p>
   170    170   <dl class="doctools_definitions">
   171    171   <dt><a name="1"><b class="cmd">thread::create</b> <span class="opt">?-joinable?</span> <span class="opt">?-preserved?</span> <span class="opt">?script?</span></a></dt>
................................................................................
   193    193   <p>Threads created by the <b class="cmd">thread::create</b> cannot be destroyed
   194    194   forcefully. Consequently, there is no corresponding thread destroy
   195    195   command. A thread may only be released using the <b class="cmd">thread::release</b>
   196    196   and if its internal reference count drops to zero, the thread is
   197    197   marked for exit. This kicks the thread out of the event loop
   198    198   servicing and the thread continues to execute commands passed in
   199    199   the <b class="option">script</b> argument, following the <b class="cmd">thread::wait</b>
   200         -command. If this was the last command in the script, as usualy the
          200  +command. If this was the last command in the script, as usually the
   201    201   case, the thread will exit.</p>
   202    202   <p>It is possible to create a situation in which it may be impossible
   203    203   to terminate the thread, for example by putting some endless loop
   204    204   after the <b class="cmd">thread::wait</b> or entering the event loop again by
   205    205   doing an vwait-type of command. In such cases, the thread may never
   206    206   exit. This is considered to be a bad practice and should be avoided
   207    207   if possible. This is best illustrated by the example below:</p>
................................................................................
   220    220   wait endlessly for events. There is no way one can terminate such thread,
   221    221   so you wouldn't want to do this!</p>
   222    222   <p>Each newly created has its internal reference counter set to 0 (zero),
   223    223   i.e. it is unreserved. This counter gets incremented by a call to
   224    224   <b class="cmd">thread::preserve</b> and decremented by a call to <b class="cmd">thread::release</b>
   225    225   command. These two commands implement simple but effective thread
   226    226   reservation system and offer predictable and controllable thread
   227         -termination capabilities. It is however possible to create initialy
          227  +termination capabilities. It is however possible to create initially
   228    228   preserved threads by using flag <b class="option">-preserved</b> of the
   229    229   <b class="cmd">thread::create</b> command. Threads created with this flag have the
   230    230   initial value of the reference counter of 1 (one), and are thus
   231    231   initially marked reserved.</p></dd>
   232    232   <dt><a name="2"><b class="cmd">thread::preserve</b> <span class="opt">?id?</span></a></dt>
   233    233   <dd><p>This command increments the thread reference counter. Each call
   234    234   to this command increments the reference counter by one (1).
................................................................................
   291    291   until there are no further invocations of the interpreter left on the
   292    292   call stack. If <i class="arg">result</i> is present, it will be used as the error
   293    293   message string; otherwise, a default error message string will be used.</p></dd>
   294    294   <dt><a name="7"><b class="cmd">thread::unwind</b></a></dt>
   295    295   <dd><p>Use of this command is deprecated in favour of more advanced thread
   296    296   reservation system implemented with <b class="cmd">thread::preserve</b> and
   297    297   <b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::unwind</b>
   298         -command will dissapear in some future major release of the extension.</p>
          298  +command will disappear in some future major release of the extension.</p>
   299    299   <p>This command stops a prior <b class="cmd">thread::wait</b> command. Execution of
   300    300   the script passed to newly created thread will continue from the
   301    301   <b class="cmd">thread::wait</b> command. If <b class="cmd">thread::wait</b> was the last command
   302    302   in the script, the thread will exit. The command returns empty result
   303    303   but may trigger Tcl error with the message &quot;target thread died&quot; in some
   304    304   situations.</p></dd>
   305    305   <dt><a name="8"><b class="cmd">thread::exit</b> <span class="opt">?status?</span></a></dt>
   306    306   <dd><p>Use of this command is deprecated in favour of more advanced thread
   307    307   reservation system implemented with <b class="cmd">thread::preserve</b> and
   308    308   <b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::exit</b>
   309         -command will dissapear in some future major release of the extension.</p>
          309  +command will disappear in some future major release of the extension.</p>
   310    310   <p>This command forces a thread stuck in the <b class="cmd">thread::wait</b> command to
   311         -unconditionaly exit. The thread's exit status defaults to 666 and can be
          311  +unconditionally exit. The thread's exit status defaults to 666 and can be
   312    312   specified using the optional <i class="arg">status</i> argument. The execution of
   313    313   <b class="cmd">thread::exit</b> command is guaranteed to leave the program memory in the
   314         -unconsistent state, produce memory leaks and otherwise affect other subsytem(s)
          314  +inconsistent state, produce memory leaks and otherwise affect other subsystem(s)
   315    315   of the Tcl application in an unpredictable manner. The command returns empty
   316    316   result but may trigger Tcl error with the message &quot;target thread died&quot; in some
   317    317   situations.</p></dd>
   318    318   <dt><a name="9"><b class="cmd">thread::names</b></a></dt>
   319    319   <dd><p>This command returns a list of thread IDs. These are only for
   320    320   threads that have been created via <b class="cmd">thread::create</b> command.
   321    321   If your application creates other threads at the C level, they
................................................................................
   331    331   The target thread must enter it's event loop in order to receive
   332    332   scripts sent via this command. This is done by default for threads
   333    333   created without a startup script. Threads can enter the event loop
   334    334   explicitly by calling <b class="cmd">thread::wait</b> or any other relevant Tcl/Tk
   335    335   command, like <b class="cmd">update</b>, <b class="cmd">vwait</b>, etc.</p>
   336    336   <p>Optional <b class="option">varname</b> specifies name of the variable to store
   337    337   the result of the <i class="arg">script</i>. Without the <b class="option">-async</b> flag,
   338         -the command returns the evaluation code, similarily to the standard
          338  +the command returns the evaluation code, similarly to the standard
   339    339   Tcl <b class="cmd">catch</b> command. If, however, the <b class="option">-async</b> flag is
   340    340   specified, the command returns immediately and caller can later
   341    341   <b class="cmd">vwait</b> on <span class="opt">?varname?</span> to get the result of the passed <i class="arg">script</i></p>
   342    342   <pre class="doctools_example">
   343    343       set t1 [thread::create]
   344    344       set t2 [thread::create]
   345    345       thread::send -async $t1 &quot;set a 1&quot; result
................................................................................
   393    393   Upon the join the handle of the thread has gone out of scope and
   394    394   should not be used any more.</p></dd>
   395    395   <dt><a name="16"><b class="cmd">thread::configure</b> <i class="arg">id</i> <span class="opt">?option?</span> <span class="opt">?value?</span> <span class="opt">?...?</span></a></dt>
   396    396   <dd><p>This command configures various low-level aspects of the thread with
   397    397   ID <i class="arg">id</i> in the similar way as the standard Tcl command
   398    398   <b class="cmd">fconfigure</b> configures some Tcl channel options. Options currently
   399    399   supported are: <b class="option">-eventmark</b> and <b class="option">-unwindonerror</b>.</p>
   400         -<p>The <b class="option">-eventmark</b> option, when set, limits the number of
   401         -asynchronously posted scripts to the thread event loop.
   402         -The <b class="cmd">thread::send -async</b> command will block until the number
   403         -of pending scripts in the event loop does not drop below the value
   404         -configured with <b class="option">-eventmark</b>. Default value for the
   405         -<b class="option">-eventmark</b> is 0 (zero) which effectively disables the checking,
   406         -i.e. allows for unlimited number of posted scripts.</p>
   407         -<p>The <b class="option">-unwindonerror</b> option, when set, causes the
   408         -target thread to unwind if the result of the script processing
   409         -resulted in error. Default value for the <b class="option">-unwindonerror</b>
   410         -is 0 (false), i.e. thread continues to process scripts after one
   411         -of the posted scripts fails.</p></dd>
          400  +<p>When <b class="option">-eventmark</b> is provided with a value greater than 0 (zero), that
          401  +value is the maximum number of asynchronously posted scripts that may be
          402  +pending for the thread.  <b class="cmd">thread::send -async</b> blocks until the number of
          403  +pending scripts in the event loop drops below the <b class="option">-eventmark</b> value.</p>
          404  +<p>When <b class="option">-unwindonerror</b> is provided with a value of true, an error result
          405  +in a script causes the thread to unwind, making it unavailable to evaluate
          406  +additional scripts.</p></dd>
   412    407   <dt><a name="17"><b class="cmd">thread::transfer</b> <i class="arg">id</i> <i class="arg">channel</i></a></dt>
   413    408   <dd><p>This moves the specified <i class="arg">channel</i> from the current thread
   414    409   and interpreter to the main interpreter of the thread with the
   415    410   given <i class="arg">id</i>. After the move the current interpreter has no
   416    411   access to the channel any more, but the main interpreter of the
   417    412   target thread will be able to use it from now on.
   418    413   The command waits until the other thread has incorporated the
................................................................................
   446    441   (or the same) thread attaches the channel again with <b class="cmd">thread::attach</b>.
   447    442   Restrictions: same as for transferring shared channels with the
   448    443   <b class="cmd">thread::transfer</b> command.</p></dd>
   449    444   <dt><a name="19"><b class="cmd">thread::attach</b> <i class="arg">channel</i></a></dt>
   450    445   <dd><p>This attaches the previously detached <i class="arg">channel</i> in the
   451    446   current thread/interpreter. For already existing channels,
   452    447   the command does nothing, i.e. it is not an error to attach the
   453         -same channel more than once. The first operation will actualy
          448  +same channel more than once. The first operation will actually
   454    449   perform the operation, while all subsequent operation will just
   455    450   do nothing. Command throws error if the <i class="arg">channel</i> cannot be
   456    451   found in the list of detached channels and/or in the current
   457    452   interpreter.</p></dd>
   458    453   <dt><a name="20"><b class="cmd">thread::mutex</b></a></dt>
   459    454   <dd><p>Mutexes are most common thread synchronization primitives.
   460    455   They are used to synchronize access from two or more threads to one or
................................................................................
   489    484   <dd><p>Unlocks the <i class="arg">mutex</i> so some other thread may lock it again.
   490    485   Attempt to unlock the already unlocked mutex will throw Tcl error.</p></dd>
   491    486   </dl></dd>
   492    487   <dt><a name="25"><b class="cmd">thread::rwmutex</b></a></dt>
   493    488   <dd><p>This command creates many-readers/single-writer mutexes. Reader/writer
   494    489   mutexes allow you to serialize access to a shared resource more optimally.
   495    490   In situations where a shared resource gets mostly read and seldom modified,
   496         -you might gain some performace by using reader/writer mutexes instead of
          491  +you might gain some performance by using reader/writer mutexes instead of
   497    492   exclusive or recursive mutexes.</p>
   498    493   <p>For reading the resource, thread should obtain a read lock on the resource.
   499    494   Read lock is non-exclusive, meaning that more than one thread can
   500    495   obtain a read lock to the same resource, without waiting on other readers.
   501    496   For changing the resource, however, a thread must obtain a exclusive
   502    497   write lock. This lock effectively blocks all threads from gaining the
   503    498   read-lock while the resource is been modified by the writer thread.
................................................................................
   524    519   Attempt to unlock already unlocked <i class="arg">mutex</i> will throw Tcl error.</p></dd>
   525    520   </dl></dd>
   526    521   <dt><a name="31"><b class="cmd">thread::cond</b></a></dt>
   527    522   <dd><p>This command provides script-level access to condition variables.
   528    523   A condition variable creates a safe environment for the program
   529    524   to test some condition, sleep on it when false and be awakened
   530    525   when it might have become true. A condition variable is always
   531         -used in the conjuction with an exclusive mutex. If you attempt
   532         -to use other type of mutex in conjuction with the condition
          526  +used in the conjunction with an exclusive mutex. If you attempt
          527  +to use other type of mutex in conjunction with the condition
   533    528   variable, a Tcl error will be thrown.</p>
   534    529   <p>The command supports following subcommands and options:</p>
   535    530   <dl class="doctools_definitions">
   536    531   <dt><a name="32"><b class="cmd">thread::cond</b> <b class="method">create</b></a></dt>
   537    532   <dd><p>Creates the condition variable and returns it's opaque handle.
   538    533   This handle should be used for any future reference to newly
   539    534   created condition variable.</p></dd>

Changes to doc/html/tpool.html.

     1      1   
     2         -<html><head>
            2  +<!DOCTYPE html><html><head>
     3      3   <title>tpool - Tcl Threading</title>
     4      4   <style type="text/css"><!--
     5      5       HTML {
     6      6   	background: 	#FFFFFF;
     7      7   	color: 		black;
     8      8       }
     9      9       BODY {
................................................................................
    88     88       }
    89     89       UL.doctools_requirements {
    90     90   	margin-bottom: 	1em;
    91     91   	border-bottom:	1px solid black;
    92     92       }
    93     93   --></style>
    94     94   </head>
    95         -<! -- Generated from file '' by tcllib/doctools with format 'html'
           95  +<!-- Generated from file '' by tcllib/doctools with format 'html'
    96     96      -->
    97         -<! -- tpool.n
           97  +<!-- tpool.n
    98     98      -->
    99     99   <body><div class="doctools">
   100    100   <h1 class="doctools_title">tpool(n) 2.8  &quot;Tcl Threading&quot;</h1>
   101    101   <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
   102    102   <p>tpool - Part of the Tcl threading extension implementing pools of worker threads.</p>
   103    103   </div>
   104    104   <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
................................................................................
   151    151   <dl class="doctools_options">
   152    152   <dt><b class="option">-minworkers</b> <i class="arg">number</i></dt>
   153    153   <dd><p>Minimum number of worker threads needed for this threadpool instance.
   154    154   During threadpool creation, the implementation will create somany
   155    155   worker threads upfront and will keep at least number of them alive
   156    156   during the lifetime of the threadpool instance.
   157    157   Default value of this parameter is 0 (zero). which means that a newly
   158         -threadpool will have no worker threads initialy. All worker threads
          158  +threadpool will have no worker threads initially. All worker threads
   159    159   will be started on demand by callers running <b class="cmd">tpool::post</b> command
   160    160   and posting jobs to the job queue.</p></dd>
   161    161   <dt><b class="option">-maxworkers</b> <i class="arg">number</i></dt>
   162    162   <dd><p>Maximum number of worker threads allowed for this threadpool instance.
   163    163   If a new job is pending and there are no idle worker threads available,
   164    164   the implementation will try to create new worker thread. If the number
   165    165   of available worker threads is lower than the given number,
................................................................................
   191    191   used to load packages and commands in the worker, set default variables,
   192    192   create namespaces, and such. If the passed script runs into a Tcl error,
   193    193   the worker will not be created and the initiating command (either the
   194    194   <b class="cmd">tpool::create</b> or <b class="cmd">tpool::post</b>) will throw error.
   195    195   Default value for this option is unspecified, hence, the Tcl interpreter of
   196    196   the worker thread will contain just the initial set of Tcl commands.</p></dd>
   197    197   <dt><b class="option">-exitcmd</b> <i class="arg">script</i></dt>
   198         -<dd><p>Sets a Tcl script run when the idle worker thread exits. This is normaly
          198  +<dd><p>Sets a Tcl script run when the idle worker thread exits. This is normally
   199    199   used to cleanup the state of the worker thread, release reserved resources,
   200    200   cleanup memory and such.
   201    201   Default value for this option is unspecified, thus no Tcl script will run
   202    202   on the worker thread exit.</p></dd>
   203    203   </dl></dd>
   204    204   <dt><a name="2"><b class="cmd">tpool::names</b></a></dt>
   205    205   <dd><p>This command returns a list of IDs of threadpools created with the

Changes to doc/html/tsv.html.

     1      1   
     2         -<html><head>
            2  +<!DOCTYPE html><html><head>
     3      3   <title>tsv - Tcl Threading</title>
     4      4   <style type="text/css"><!--
     5      5       HTML {
     6      6   	background: 	#FFFFFF;
     7      7   	color: 		black;
     8      8       }
     9      9       BODY {
................................................................................
    88     88       }
    89     89       UL.doctools_requirements {
    90     90   	margin-bottom: 	1em;
    91     91   	border-bottom:	1px solid black;
    92     92       }
    93     93   --></style>
    94     94   </head>
    95         -<! -- Generated from file '' by tcllib/doctools with format 'html'
           95  +<!-- Generated from file '' by tcllib/doctools with format 'html'
    96     96      -->
    97         -<! -- tsv.n
           97  +<!-- tsv.n
    98     98      -->
    99     99   <body><div class="doctools">
   100    100   <h1 class="doctools_title">tsv(n) 2.8  &quot;Tcl Threading&quot;</h1>
   101    101   <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
   102    102   <p>tsv - Part of the Tcl threading extension allowing script level manipulation of data shared between threads.</p>
   103    103   </div>
   104    104   <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
................................................................................
   161    161   </div>
   162    162   </div>
   163    163   <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
   164    164   <p>This section describes commands implementing thread shared variables.
   165    165   A thread shared variable is very similar to a Tcl array but in
   166    166   contrast to a Tcl array it is created in shared memory and can
   167    167   be accessed from many threads at the same time. Important feature of
   168         -thread shared variable is that each access to the variable is internaly
          168  +thread shared variable is that each access to the variable is internally
   169    169   protected by a mutex so script programmer does not have to take care
   170    170   about locking the variable himself.</p>
   171    171   <p>Thread shared variables are not bound to any thread explicitly. That
   172    172   means that when a thread which created any of thread shared variables
   173    173   exits, the variable and associated memory is not unset/reclaimed.
   174    174   User has to explicitly unset the variable to reclaim the memory
   175    175   consumed by the variable.</p>
   176    176   </div>
   177    177   <div id="section2" class="doctools_section"><h2><a name="section2">ELEMENT COMMANDS</a></h2>
   178    178   <dl class="doctools_definitions">
   179    179   <dt><a name="1"><b class="cmd">tsv::names</b> <span class="opt">?pattern?</span></a></dt>
   180    180   <dd><p>Returns names of shared variables matching optional <span class="opt">?pattern?</span>
   181         -or all known variables if pattern is ommited.</p></dd>
          181  +or all known variables if pattern is omitted.</p></dd>
   182    182   <dt><a name="2"><b class="cmd">tsv::object</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
   183    183   <dd><p>Creates object accessor command for the <i class="arg">element</i> in the
   184    184   shared variable <i class="arg">varname</i>. Using this command, one can apply most
   185    185   of the other shared variable commands as method functions of
   186    186   the element object command. The object command is automatically
   187    187   deleted when the element which this command is pointing to is unset.</p>
   188    188   <pre class="doctools_example">
................................................................................
   191    191       % $string append &quot; appended&quot;
   192    192       =&gt; A shared string appended
   193    193   </pre>
   194    194   </dd>
   195    195   <dt><a name="3"><b class="cmd">tsv::set</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?value?</span></a></dt>
   196    196   <dd><p>Sets the value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i>
   197    197   to <i class="arg">value</i> and returns the value to caller. The <i class="arg">value</i>
   198         -may be ommited, in which case the command will return the current
          198  +may be omitted, in which case the command will return the current
   199    199   value of the element. If the element cannot be found, error is triggered.</p></dd>
   200    200   <dt><a name="4"><b class="cmd">tsv::get</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?namedvar?</span></a></dt>
   201    201   <dd><p>Retrieves the value of the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>.
   202    202   If the optional argument <i class="arg">namedvar</i> is given, the value is
   203    203   stored in the named variable. Return value of the command depends
   204    204   of the existence of the optional argument <i class="arg">namedvar</i>.
   205         -If the argument is ommited and the requested element cannot be found
          205  +If the argument is omitted and the requested element cannot be found
   206    206   in the shared array, the command triggers error. If, however, the
   207    207   optional argument is given on the command line, the command returns
   208    208   true (1) if the element is found or false (0) if the element is not found.</p></dd>
   209    209   <dt><a name="5"><b class="cmd">tsv::unset</b> <i class="arg">varname</i> <span class="opt">?element?</span></a></dt>
   210    210   <dd><p>Unsets the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>.
   211    211   If the optional element is not given, it deletes the variable.</p></dd>
   212    212   <dt><a name="6"><b class="cmd">tsv::exists</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
   213         -<dd><p>Checks wether the <i class="arg">element</i> exists in the shared variable <i class="arg">varname</i>
          213  +<dd><p>Checks whether the <i class="arg">element</i> exists in the shared variable <i class="arg">varname</i>
   214    214   and returns true (1) if it does or false (0) if it doesn't.</p></dd>
   215    215   <dt><a name="7"><b class="cmd">tsv::pop</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
   216    216   <dd><p>Returns value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i>
   217    217   and unsets the element, all in one atomic operation.</p></dd>
   218    218   <dt><a name="8"><b class="cmd">tsv::move</b> <i class="arg">varname</i> <i class="arg">oldname</i> <i class="arg">newname</i></a></dt>
   219    219   <dd><p>Renames the element <i class="arg">oldname</i> to the <i class="arg">newname</i> in the
   220    220   shared variable <i class="arg">varname</i>. This effectively performs an get/unset/set
   221    221   sequence of operations but all in one atomic step.</p></dd>
   222    222   <dt><a name="9"><b class="cmd">tsv::incr</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?count?</span></a></dt>
   223    223   <dd><p>Similar to standard Tcl <b class="cmd">incr</b> command but increments the value
   224         -of the <i class="arg">element</i> in shared variaboe <i class="arg">varname</i> instead of
          224  +of the <i class="arg">element</i> in shared variable <i class="arg">varname</i> instead of
   225    225   the Tcl variable.</p></dd>
   226    226   <dt><a name="10"><b class="cmd">tsv::append</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt>
   227    227   <dd><p>Similar to standard Tcl <b class="cmd">append</b> command but appends one or more
   228    228   values to the <i class="arg">element</i> in shared variable <i class="arg">varname</i> instead of the
   229    229   Tcl variable.</p></dd>
   230    230   <dt><a name="11"><b class="cmd">tsv::lock</b> <i class="arg">varname</i> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt>
   231    231   <dd><p>This command concatenates passed arguments and evaluates the
................................................................................
   287    287   <dt><a name="21"><b class="cmd">tsv::lpop</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt>
   288    288   <dd><p>Similar to the standard Tcl <b class="cmd">lindex</b> command but in addition to
   289    289   returning, it also splices the value out of the <i class="arg">element</i>
   290    290   from the shared variable <i class="arg">varname</i> in one atomic operation.
   291    291   In contrast to the Tcl <b class="cmd">lindex</b> command, this command returns
   292    292   no value to the caller.</p></dd>
   293    293   <dt><a name="22"><b class="cmd">tsv::lpush</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt>
   294         -<dd><p>This command performes the opposite of the <b class="cmd">tsv::lpop</b> command.
          294  +<dd><p>This command performs the opposite of the <b class="cmd">tsv::lpop</b> command.
   295    295   As its counterpart, it returns no value to the caller.</p></dd>
   296    296   </dl>
   297    297   </div>
   298    298   <div id="section4" class="doctools_section"><h2><a name="section4">ARRAY COMMANDS</a></h2>
   299    299   <p>This command supports most of the options of the standard Tcl
   300    300   <b class="cmd">array</b> command. In addition to those, it allows binding
   301         -a shared variable to some persisten storage databases. Currently the persistent
          301  +a shared variable to some persistent storage databases. Currently the persistent
   302    302   options supported are the famous GNU Gdbm and LMDB. These options have to be
   303    303   selected during the package compilation time.
   304    304   The implementation provides hooks for defining other persistency layers, if
   305    305   needed.</p>
   306    306   <dl class="doctools_definitions">
   307    307   <dt><a name="23"><b class="cmd">tsv::array set</b> <i class="arg">varname</i> <i class="arg">list</i></a></dt>
   308    308   <dd><p>Does the same as standard Tcl <b class="cmd">array set</b>.</p></dd>
................................................................................
   368    368   command will return 0, and <i class="arg">retvar</i> will be left unchanged. If {} is
   369    369   specified for <i class="arg">retvar</i>, the value is not returned, allowing the Tcl
   370    370   programmer to determine if a <i class="arg">key</i> is present in a keyed list without
   371    371   setting a variable as a side-effect.</p></dd>
   372    372   <dt><a name="33"><b class="cmd">tsv::keylkeys</b> <i class="arg">varname</i> <i class="arg">keylist</i> <span class="opt">?key?</span></a></dt>
   373    373   <dd><p>Return  the a list of the keys in the keyed list <i class="arg">keylist</i> in the
   374    374   shared variable <i class="arg">varname</i>. If <i class="arg">key</i> is specified, then it is
   375         -the name of a key field who's subfield keys are to be retrieved.</p></dd>
          375  +the name of a key field whose subfield keys are to be retrieved.</p></dd>
   376    376   <dt><a name="34"><b class="cmd">tsv::keylset</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <i class="arg">value</i> <span class="opt">?key value..?</span></a></dt>
   377    377   <dd><p>Set the value associated with <i class="arg">key</i>, in the keyed list <i class="arg">keylist</i>
   378    378   to <i class="arg">value</i>. If the <i class="arg">keylist</i> does not exists, it is created.
   379    379   If <i class="arg">key</i> is not currently in the list, it will be added. If it already
   380    380   exists, <i class="arg">value</i> replaces the existing value. Multiple keywords and
   381    381   values may be specified, if desired.</p></dd>
   382    382   </dl>
................................................................................
   389    389   improving performance. Special care has been taken to assure that all
   390    390   object data is properly locked and deep-copied when moving objects between
   391    391   threads.</p>
   392    392   <p>Due to the internal design of the Tcl core, there is no provision of full
   393    393   integration of shared variables within the Tcl syntax, unfortunately. All
   394    394   access to shared data must be performed with the supplied package commands.
   395    395   Also, variable traces are not supported. But even so, benefits of easy,
   396         -simple and safe shared data manipulation outweights imposed limitations.</p>
          396  +simple and safe shared data manipulation outweighs imposed limitations.</p>
   397    397   </div>
   398    398   <div id="section7" class="doctools_section"><h2><a name="section7">CREDITS</a></h2>
   399    399   <p>Thread shared variables are inspired by the nsv interface found in
   400    400   AOLserver, a highly scalable Web server from America Online.</p>
   401    401   </div>
   402    402   <div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
   403    403   <p>thread, tpool, ttrace</p>
   404    404   </div>
   405    405   <div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
   406    406   <p>locking, synchronization, thread shared data, threads</p>
   407    407   </div>
   408    408   </div></body></html>
   409    409   

Changes to doc/html/ttrace.html.

     1      1   
     2         -<html><head>
            2  +<!DOCTYPE html><html><head>
     3      3   <title>ttrace - Tcl Threading</title>
     4      4   <style type="text/css"><!--
     5      5       HTML {
     6      6   	background: 	#FFFFFF;
     7      7   	color: 		black;
     8      8       }
     9      9       BODY {
................................................................................
    88     88       }
    89     89       UL.doctools_requirements {
    90     90   	margin-bottom: 	1em;
    91     91   	border-bottom:	1px solid black;
    92     92       }
    93     93   --></style>
    94     94   </head>
    95         -<! -- Generated from file '' by tcllib/doctools with format 'html'
           95  +<!-- Generated from file '' by tcllib/doctools with format 'html'
    96     96      -->
    97         -<! -- ttrace.n
           97  +<!-- ttrace.n
    98     98      -->
    99     99   <body><div class="doctools">
   100    100   <h1 class="doctools_title">ttrace(n) 2.8  &quot;Tcl Threading&quot;</h1>
   101    101   <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
   102    102   <p>ttrace - Trace-based interpreter initialization</p>
   103    103   </div>
   104    104   <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
................................................................................
   138    138   <li><a href="#16"><b class="cmd">ttrace::delentry</b> <i class="arg">cmd</i></a></li>
   139    139   <li><a href="#17"><b class="cmd">ttrace::preload</b> <i class="arg">cmd</i></a></li>
   140    140   </ul>
   141    141   </div>
   142    142   </div>
   143    143   <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
   144    144   <p>This package creates a framework for on-demand replication of the
   145         -interpreter state accross threads in an multithreading application.
          145  +interpreter state across threads in an multithreading application.
   146    146   It relies on the mechanics of Tcl command tracing and the Tcl
   147    147   <b class="cmd">unknown</b> command and mechanism.</p>
   148    148   <p>The package requires Tcl threading extension but can be alternatively
   149    149   used stand-alone within the AOLserver, a scalable webserver from
   150    150   America Online.</p>
   151    151   <p>In a nutshell, a short sample illustrating the usage of the ttrace
   152    152   with the Tcl threading extension:</p>
................................................................................
   182    182   epoch change. For the Tcl threading extension, all threads created by
   183    183   the extension are automatically updated. If the command execution
   184    184   resulted in Tcl error, no state propagation takes place.</p>
   185    185   <p>This is the most important user-level command of the package as
   186    186   it wraps most of the commands described below. This greatly
   187    187   simplifies things, because user need to learn just this (one)
   188    188   command in order to effectively use the package. Other commands,
   189         -as desribed below, are included mostly for the sake of completeness.</p></dd>
          189  +as described below, are included mostly for the sake of completeness.</p></dd>
   190    190   <dt><a name="2"><b class="cmd">ttrace::enable</b></a></dt>
   191    191   <dd><p>Activates all registered callbacks in the framework
   192    192   and starts a new trace epoch. The trace epoch encapsulates all
   193    193   changes done to the interpreter during the time traces are activated.</p></dd>
   194    194   <dt><a name="3"><b class="cmd">ttrace::disable</b></a></dt>
   195    195   <dd><p>Deactivates all registered callbacks in the framework
   196    196   and closes the current trace epoch.</p></dd>
................................................................................
   198    198   <dd><p>Used to clean-up all on-demand loaded resources in the interpreter.
   199    199   It effectively brings Tcl interpreter to its pristine state.</p></dd>
   200    200   <dt><a name="5"><b class="cmd">ttrace::update</b> <span class="opt">?epoch?</span></a></dt>
   201    201   <dd><p>Used to refresh the state of the interpreter to match the optional
   202    202   trace <span class="opt">?epoch?</span>. If the optional <span class="opt">?epoch?</span> is not given, it takes
   203    203   the most recent trace epoch.</p></dd>
   204    204   <dt><a name="6"><b class="cmd">ttrace::getscript</b></a></dt>
   205         -<dd><p>Returns a synthetized Tcl script which may be sourced in any interpreter.
          205  +<dd><p>Returns a synthesized Tcl script which may be sourced in any interpreter.
   206    206   This script sets the stage for the Tcl <b class="cmd">unknown</b> command so it can
   207    207   load traced resources from the in-memory database. Normally, this command
   208    208   is automatically invoked by other higher-level commands like
   209    209   <b class="cmd">ttrace::eval</b> and <b class="cmd">ttrace::update</b>.</p></dd>
   210    210   </dl>
   211    211   </div>
   212    212   <div id="section3" class="doctools_section"><h2><a name="section3">CALLBACK COMMANDS</a></h2>
   213    213   <p>A word upfront: the package already includes callbacks for tracing
   214    214   following Tcl commands: <b class="cmd">proc</b>, <b class="cmd">namespace</b>, <b class="cmd">variable</b>,
   215         -<b class="cmd">load</b>, and <b class="cmd">rename</b>. Additionaly, a set of callbacks for
   216         -tracing resources (object, clasess) for the XOTcl v1.3.8+, an
          215  +<b class="cmd">load</b>, and <b class="cmd">rename</b>. Additionally, a set of callbacks for
          216  +tracing resources (object, classes) for the XOTcl v1.3.8+, an
   217    217   OO-extension to Tcl, is also provided.
   218    218   This gives a solid base for solving most of the real-life needs and
   219    219   serves as an example for people wanting to customize the package
   220    220   to cover their specific needs.</p>
   221    221   <p>Below, you can find commands for registering callbacks in the
   222    222   framework and for writing callback scripts. These callbacks are
   223    223   invoked by the framework in order to gather interpreter state
................................................................................
   289    289   creates the requested resource in the interpreter on demand.
   290    290   This way, users can update just one interpreter (master) in one
   291    291   thread and replicate that interpreter state (or part of it) to other
   292    292   threads/interpreters in the process.</p>
   293    293   <p>Immediate benefit of such approach is the much smaller memory footprint
   294    294   of the application and much faster thread creation. By not actually
   295    295   loading all necessary procedures (and other resources) in every thread
   296         -at the thread initialization time, but by deffering this to the time the
          296  +at the thread initialization time, but by deferring this to the time the
   297    297   resource is actually referenced, significant improvements in both
   298    298   memory consumption and thread initialization time can be achieved. Some
   299    299   tests have shown that memory footprint of an multithreading Tcl application
   300    300   went down more than three times and thread startup time was reduced for
   301    301   about 50 times. Note that your mileage may vary.
   302    302   Other benefits include much finer control about what (and when) gets
   303    303   replicated from the master to other Tcl thread/interpreters.</p>

Changes to doc/man/thread.n.

   348    348   \fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms?
   349    349   .sp
   350    350   .BE
   351    351   .SH DESCRIPTION
   352    352   The \fBthread\fR extension creates threads that contain Tcl
   353    353   interpreters, and it lets you send scripts to those threads for
   354    354   evaluation\&.
   355         -Additionaly, it provides script-level access to basic thread
          355  +Additionally, it provides script-level access to basic thread
   356    356   synchronization primitives, like mutexes and condition variables\&.
   357    357   .SH COMMANDS
   358    358   This section describes commands for creating and destroying threads
   359    359   and sending scripts to threads for evaluation\&.
   360    360   .TP
   361    361   \fBthread::create\fR ?-joinable? ?-preserved? ?script?
   362    362   This command creates a thread that contains a Tcl interpreter\&.
................................................................................
   386    386   Threads created by the \fBthread::create\fR cannot be destroyed
   387    387   forcefully\&. Consequently, there is no corresponding thread destroy
   388    388   command\&. A thread may only be released using the \fBthread::release\fR
   389    389   and if its internal reference count drops to zero, the thread is
   390    390   marked for exit\&. This kicks the thread out of the event loop
   391    391   servicing and the thread continues to execute commands passed in
   392    392   the \fBscript\fR argument, following the \fBthread::wait\fR
   393         -command\&. If this was the last command in the script, as usualy the
          393  +command\&. If this was the last command in the script, as usually the
   394    394   case, the thread will exit\&.
   395    395   .sp
   396    396   It is possible to create a situation in which it may be impossible
   397    397   to terminate the thread, for example by putting some endless loop
   398    398   after the \fBthread::wait\fR or entering the event loop again by
   399    399   doing an vwait-type of command\&. In such cases, the thread may never
   400    400   exit\&. This is considered to be a bad practice and should be avoided
................................................................................
   419    419   so you wouldn't want to do this!
   420    420   .sp
   421    421   Each newly created has its internal reference counter set to 0 (zero),
   422    422   i\&.e\&. it is unreserved\&. This counter gets incremented by a call to
   423    423   \fBthread::preserve\fR and decremented by a call to \fBthread::release\fR
   424    424   command\&. These two commands implement simple but effective thread
   425    425   reservation system and offer predictable and controllable thread
   426         -termination capabilities\&. It is however possible to create initialy
          426  +termination capabilities\&. It is however possible to create initially
   427    427   preserved threads by using flag \fB-preserved\fR of the
   428    428   \fBthread::create\fR command\&. Threads created with this flag have the
   429    429   initial value of the reference counter of 1 (one), and are thus
   430    430   initially marked reserved\&.
   431    431   .TP
   432    432   \fBthread::preserve\fR ?id?
   433    433   This command increments the thread reference counter\&. Each call
................................................................................
   501    501   call stack\&. If \fIresult\fR is present, it will be used as the error
   502    502   message string; otherwise, a default error message string will be used\&.
   503    503   .TP
   504    504   \fBthread::unwind\fR
   505    505   Use of this command is deprecated in favour of more advanced thread
   506    506   reservation system implemented with \fBthread::preserve\fR and
   507    507   \fBthread::release\fR commands\&. Support for \fBthread::unwind\fR
   508         -command will dissapear in some future major release of the extension\&.
          508  +command will disappear in some future major release of the extension\&.
   509    509   .sp
   510    510   This command stops a prior \fBthread::wait\fR command\&. Execution of
   511    511   the script passed to newly created thread will continue from the
   512    512   \fBthread::wait\fR command\&. If \fBthread::wait\fR was the last command
   513    513   in the script, the thread will exit\&. The command returns empty result
   514    514   but may trigger Tcl error with the message "target thread died" in some
   515    515   situations\&.
   516    516   .TP
   517    517   \fBthread::exit\fR ?status?
   518    518   Use of this command is deprecated in favour of more advanced thread
   519    519   reservation system implemented with \fBthread::preserve\fR and
   520    520   \fBthread::release\fR commands\&. Support for \fBthread::exit\fR
   521         -command will dissapear in some future major release of the extension\&.
          521  +command will disappear in some future major release of the extension\&.
   522    522   .sp
   523    523   This command forces a thread stuck in the \fBthread::wait\fR command to
   524         -unconditionaly exit\&. The thread's exit status defaults to 666 and can be
          524  +unconditionally exit\&. The thread's exit status defaults to 666 and can be
   525    525   specified using the optional \fIstatus\fR argument\&. The execution of
   526    526   \fBthread::exit\fR command is guaranteed to leave the program memory in the
   527         -unconsistent state, produce memory leaks and otherwise affect other subsytem(s)
          527  +inconsistent state, produce memory leaks and otherwise affect other subsystem(s)
   528    528   of the Tcl application in an unpredictable manner\&. The command returns empty
   529    529   result but may trigger Tcl error with the message "target thread died" in some
   530    530   situations\&.
   531    531   .TP
   532    532   \fBthread::names\fR
   533    533   This command returns a list of thread IDs\&. These are only for
   534    534   threads that have been created via \fBthread::create\fR command\&.
................................................................................
   548    548   scripts sent via this command\&. This is done by default for threads
   549    549   created without a startup script\&. Threads can enter the event loop
   550    550   explicitly by calling \fBthread::wait\fR or any other relevant Tcl/Tk
   551    551   command, like \fBupdate\fR, \fBvwait\fR, etc\&.
   552    552   .sp
   553    553   Optional \fBvarname\fR specifies name of the variable to store
   554    554   the result of the \fIscript\fR\&. Without the \fB-async\fR flag,
   555         -the command returns the evaluation code, similarily to the standard
          555  +the command returns the evaluation code, similarly to the standard
   556    556   Tcl \fBcatch\fR command\&. If, however, the \fB-async\fR flag is
   557    557   specified, the command returns immediately and caller can later
   558    558   \fBvwait\fR on ?varname? to get the result of the passed \fIscript\fR
   559    559   .CS
   560    560   
   561    561   
   562    562       set t1 [thread::create]
................................................................................
   623    623   .TP
   624    624   \fBthread::configure\fR \fIid\fR ?option? ?value? ?\&.\&.\&.?
   625    625   This command configures various low-level aspects of the thread with
   626    626   ID \fIid\fR in the similar way as the standard Tcl command
   627    627   \fBfconfigure\fR configures some Tcl channel options\&. Options currently
   628    628   supported are: \fB-eventmark\fR and \fB-unwindonerror\fR\&.
   629    629   .sp
   630         -The \fB-eventmark\fR option, when set, limits the number of
   631         -asynchronously posted scripts to the thread event loop\&.
   632         -The \fBthread::send -async\fR command will block until the number
   633         -of pending scripts in the event loop does not drop below the value
   634         -configured with \fB-eventmark\fR\&. Default value for the
   635         -\fB-eventmark\fR is 0 (zero) which effectively disables the checking,
   636         -i\&.e\&. allows for unlimited number of posted scripts\&.
          630  +When \fB-eventmark\fR is provided with a value greater than 0 (zero), that
          631  +value is the maximum number of asynchronously posted scripts that may be
          632  +pending for the thread\&.  \fBthread::send -async\fR blocks until the number of
          633  +pending scripts in the event loop drops below the \fB-eventmark\fR value\&.
   637    634   .sp
   638         -The \fB-unwindonerror\fR option, when set, causes the
   639         -target thread to unwind if the result of the script processing
   640         -resulted in error\&. Default value for the \fB-unwindonerror\fR
   641         -is 0 (false), i\&.e\&. thread continues to process scripts after one
   642         -of the posted scripts fails\&.
          635  +When \fB-unwindonerror\fR is provided with a value of true, an error result
          636  +in a script causes the thread to unwind, making it unavailable to evaluate
          637  +additional scripts\&.
   643    638   .TP
   644    639   \fBthread::transfer\fR \fIid\fR \fIchannel\fR
   645    640   This moves the specified \fIchannel\fR from the current thread
   646    641   and interpreter to the main interpreter of the thread with the
   647    642   given \fIid\fR\&. After the move the current interpreter has no
   648    643   access to the channel any more, but the main interpreter of the
   649    644   target thread will be able to use it from now on\&.
................................................................................
   683    678   Restrictions: same as for transferring shared channels with the
   684    679   \fBthread::transfer\fR command\&.
   685    680   .TP
   686    681   \fBthread::attach\fR \fIchannel\fR
   687    682   This attaches the previously detached \fIchannel\fR in the
   688    683   current thread/interpreter\&. For already existing channels,
   689    684   the command does nothing, i\&.e\&. it is not an error to attach the
   690         -same channel more than once\&. The first operation will actualy
          685  +same channel more than once\&. The first operation will actually
   691    686   perform the operation, while all subsequent operation will just
   692    687   do nothing\&. Command throws error if the \fIchannel\fR cannot be
   693    688   found in the list of detached channels and/or in the current
   694    689   interpreter\&.
   695    690   .TP
   696    691   \fBthread::mutex\fR
   697    692   Mutexes are most common thread synchronization primitives\&.
................................................................................
   735    730   .RE
   736    731   .sp
   737    732   .TP
   738    733   \fBthread::rwmutex\fR
   739    734   This command creates many-readers/single-writer mutexes\&. Reader/writer
   740    735   mutexes allow you to serialize access to a shared resource more optimally\&.
   741    736   In situations where a shared resource gets mostly read and seldom modified,
   742         -you might gain some performace by using reader/writer mutexes instead of
          737  +you might gain some performance by using reader/writer mutexes instead of
   743    738   exclusive or recursive mutexes\&.
   744    739   .sp
   745    740   For reading the resource, thread should obtain a read lock on the resource\&.
   746    741   Read lock is non-exclusive, meaning that more than one thread can
   747    742   obtain a read lock to the same resource, without waiting on other readers\&.
   748    743   For changing the resource, however, a thread must obtain a exclusive
   749    744   write lock\&. This lock effectively blocks all threads from gaining the
................................................................................
   779    774   .sp
   780    775   .TP
   781    776   \fBthread::cond\fR
   782    777   This command provides script-level access to condition variables\&.
   783    778   A condition variable creates a safe environment for the program
   784    779   to test some condition, sleep on it when false and be awakened
   785    780   when it might have become true\&. A condition variable is always
   786         -used in the conjuction with an exclusive mutex\&. If you attempt
   787         -to use other type of mutex in conjuction with the condition
          781  +used in the conjunction with an exclusive mutex\&. If you attempt
          782  +to use other type of mutex in conjunction with the condition
   788    783   variable, a Tcl error will be thrown\&.
   789    784   .sp
   790    785   The command supports following subcommands and options:
   791    786   .RS
   792    787   .TP
   793    788   \fBthread::cond\fR \fBcreate\fR
   794    789   Creates the condition variable and returns it's opaque handle\&.

Changes to doc/man/tpool.n.

   318    318   .TP
   319    319   \fB-minworkers\fR \fInumber\fR
   320    320   Minimum number of worker threads needed for this threadpool instance\&.
   321    321   During threadpool creation, the implementation will create somany
   322    322   worker threads upfront and will keep at least number of them alive
   323    323   during the lifetime of the threadpool instance\&.
   324    324   Default value of this parameter is 0 (zero)\&. which means that a newly
   325         -threadpool will have no worker threads initialy\&. All worker threads
          325  +threadpool will have no worker threads initially\&. All worker threads
   326    326   will be started on demand by callers running \fBtpool::post\fR command
   327    327   and posting jobs to the job queue\&.
   328    328   .TP
   329    329   \fB-maxworkers\fR \fInumber\fR
   330    330   Maximum number of worker threads allowed for this threadpool instance\&.
   331    331   If a new job is pending and there are no idle worker threads available,
   332    332   the implementation will try to create new worker thread\&. If the number
................................................................................
   363    363   create namespaces, and such\&. If the passed script runs into a Tcl error,
   364    364   the worker will not be created and the initiating command (either the
   365    365   \fBtpool::create\fR or \fBtpool::post\fR) will throw error\&.
   366    366   Default value for this option is unspecified, hence, the Tcl interpreter of
   367    367   the worker thread will contain just the initial set of Tcl commands\&.
   368    368   .TP
   369    369   \fB-exitcmd\fR \fIscript\fR
   370         -Sets a Tcl script run when the idle worker thread exits\&. This is normaly
          370  +Sets a Tcl script run when the idle worker thread exits\&. This is normally
   371    371   used to cleanup the state of the worker thread, release reserved resources,
   372    372   cleanup memory and such\&.
   373    373   Default value for this option is unspecified, thus no Tcl script will run
   374    374   on the worker thread exit\&.
   375    375   .RE
   376    376   .sp
   377    377   .TP

Changes to doc/man/tsv.n.

   347    347   .sp
   348    348   .BE
   349    349   .SH DESCRIPTION
   350    350   This section describes commands implementing thread shared variables\&.
   351    351   A thread shared variable is very similar to a Tcl array but in
   352    352   contrast to a Tcl array it is created in shared memory and can
   353    353   be accessed from many threads at the same time\&. Important feature of
   354         -thread shared variable is that each access to the variable is internaly
          354  +thread shared variable is that each access to the variable is internally
   355    355   protected by a mutex so script programmer does not have to take care
   356    356   about locking the variable himself\&.
   357    357   .PP
   358    358   Thread shared variables are not bound to any thread explicitly\&. That
   359    359   means that when a thread which created any of thread shared variables
   360    360   exits, the variable and associated memory is not unset/reclaimed\&.
   361    361   User has to explicitly unset the variable to reclaim the memory
   362    362   consumed by the variable\&.
   363    363   .SH "ELEMENT COMMANDS"
   364    364   .TP
   365    365   \fBtsv::names\fR ?pattern?
   366    366   Returns names of shared variables matching optional ?pattern?
   367         -or all known variables if pattern is ommited\&.
          367  +or all known variables if pattern is omitted\&.
   368    368   .TP
   369    369   \fBtsv::object\fR \fIvarname\fR \fIelement\fR
   370    370   Creates object accessor command for the \fIelement\fR in the
   371    371   shared variable \fIvarname\fR\&. Using this command, one can apply most
   372    372   of the other shared variable commands as method functions of
   373    373   the element object command\&. The object command is automatically
   374    374   deleted when the element which this command is pointing to is unset\&.
................................................................................
   381    381       => A shared string appended
   382    382   
   383    383   .CE
   384    384   .TP
   385    385   \fBtsv::set\fR \fIvarname\fR \fIelement\fR ?value?
   386    386   Sets the value of the \fIelement\fR in the shared variable \fIvarname\fR
   387    387   to \fIvalue\fR and returns the value to caller\&. The \fIvalue\fR
   388         -may be ommited, in which case the command will return the current
          388  +may be omitted, in which case the command will return the current
   389    389   value of the element\&. If the element cannot be found, error is triggered\&.
   390    390   .TP
   391    391   \fBtsv::get\fR \fIvarname\fR \fIelement\fR ?namedvar?
   392    392   Retrieves the value of the \fIelement\fR from the shared variable \fIvarname\fR\&.
   393    393   If the optional argument \fInamedvar\fR is given, the value is
   394    394   stored in the named variable\&. Return value of the command depends
   395    395   of the existence of the optional argument \fInamedvar\fR\&.
   396         -If the argument is ommited and the requested element cannot be found
          396  +If the argument is omitted and the requested element cannot be found
   397    397   in the shared array, the command triggers error\&. If, however, the
   398    398   optional argument is given on the command line, the command returns
   399    399   true (1) if the element is found or false (0) if the element is not found\&.
   400    400   .TP
   401    401   \fBtsv::unset\fR \fIvarname\fR ?element?
   402    402   Unsets the \fIelement\fR from the shared variable \fIvarname\fR\&.
   403    403   If the optional element is not given, it deletes the variable\&.
   404    404   .TP
   405    405   \fBtsv::exists\fR \fIvarname\fR \fIelement\fR
   406         -Checks wether the \fIelement\fR exists in the shared variable \fIvarname\fR
          406  +Checks whether the \fIelement\fR exists in the shared variable \fIvarname\fR
   407    407   and returns true (1) if it does or false (0) if it doesn't\&.
   408    408   .TP
   409    409   \fBtsv::pop\fR \fIvarname\fR \fIelement\fR
   410    410   Returns value of the \fIelement\fR in the shared variable \fIvarname\fR
   411    411   and unsets the element, all in one atomic operation\&.
   412    412   .TP
   413    413   \fBtsv::move\fR \fIvarname\fR \fIoldname\fR \fInewname\fR
   414    414   Renames the element \fIoldname\fR to the \fInewname\fR in the
   415    415   shared variable \fIvarname\fR\&. This effectively performs an get/unset/set
   416    416   sequence of operations but all in one atomic step\&.
   417    417   .TP
   418    418   \fBtsv::incr\fR \fIvarname\fR \fIelement\fR ?count?
   419    419   Similar to standard Tcl \fBincr\fR command but increments the value
   420         -of the \fIelement\fR in shared variaboe \fIvarname\fR instead of
          420  +of the \fIelement\fR in shared variable \fIvarname\fR instead of
   421    421   the Tcl variable\&.
   422    422   .TP
   423    423   \fBtsv::append\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.?
   424    424   Similar to standard Tcl \fBappend\fR command but appends one or more
   425    425   values to the \fIelement\fR in shared variable \fIvarname\fR instead of the
   426    426   Tcl variable\&.
   427    427   .TP
................................................................................
   496    496   Similar to the standard Tcl \fBlindex\fR command but in addition to
   497    497   returning, it also splices the value out of the \fIelement\fR
   498    498   from the shared variable \fIvarname\fR in one atomic operation\&.
   499    499   In contrast to the Tcl \fBlindex\fR command, this command returns
   500    500   no value to the caller\&.
   501    501   .TP
   502    502   \fBtsv::lpush\fR \fIvarname\fR \fIelement\fR ?index?
   503         -This command performes the opposite of the \fBtsv::lpop\fR command\&.
          503  +This command performs the opposite of the \fBtsv::lpop\fR command\&.
   504    504   As its counterpart, it returns no value to the caller\&.
   505    505   .PP
   506    506   .SH "ARRAY COMMANDS"
   507    507   This command supports most of the options of the standard Tcl
   508    508   \fBarray\fR command\&. In addition to those, it allows binding
   509         -a shared variable to some persisten storage databases\&. Currently the persistent
          509  +a shared variable to some persistent storage databases\&. Currently the persistent
   510    510   options supported are the famous GNU Gdbm and LMDB\&. These options have to be
   511    511   selected during the package compilation time\&.
   512    512   The implementation provides hooks for defining other persistency layers, if
   513    513   needed\&.
   514    514   .TP
   515    515   \fBtsv::array set\fR \fIvarname\fR \fIlist\fR
   516    516   Does the same as standard Tcl \fBarray set\fR\&.
................................................................................
   592    592   specified for \fIretvar\fR, the value is not returned, allowing the Tcl
   593    593   programmer to determine if a \fIkey\fR is present in a keyed list without
   594    594   setting a variable as a side-effect\&.
   595    595   .TP
   596    596   \fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key?
   597    597   Return  the a list of the keys in the keyed list \fIkeylist\fR in the
   598    598   shared variable \fIvarname\fR\&. If \fIkey\fR is specified, then it is
   599         -the name of a key field who's subfield keys are to be retrieved\&.
          599  +the name of a key field whose subfield keys are to be retrieved\&.
   600    600   .TP
   601    601   \fBtsv::keylset\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR \fIvalue\fR ?key value\&.\&.?
   602    602   Set the value associated with \fIkey\fR, in the keyed list \fIkeylist\fR
   603    603   to \fIvalue\fR\&. If the \fIkeylist\fR does not exists, it is created\&.
   604    604   If \fIkey\fR is not currently in the list, it will be added\&. If it already
   605    605   exists, \fIvalue\fR replaces the existing value\&. Multiple keywords and
   606    606   values may be specified, if desired\&.
................................................................................
   614    614   object data is properly locked and deep-copied when moving objects between
   615    615   threads\&.
   616    616   .PP
   617    617   Due to the internal design of the Tcl core, there is no provision of full
   618    618   integration of shared variables within the Tcl syntax, unfortunately\&. All
   619    619   access to shared data must be performed with the supplied package commands\&.
   620    620   Also, variable traces are not supported\&. But even so, benefits of easy,
   621         -simple and safe shared data manipulation outweights imposed limitations\&.
          621  +simple and safe shared data manipulation outweighs imposed limitations\&.
   622    622   .SH CREDITS
   623    623   Thread shared variables are inspired by the nsv interface found in
   624    624   AOLserver, a highly scalable Web server from America Online\&.
   625    625   .SH "SEE ALSO"
   626    626   thread, tpool, ttrace
   627    627   .SH KEYWORDS
   628    628   locking, synchronization, thread shared data, threads

Changes to doc/man/ttrace.n.

   310    310   \fBttrace::delentry\fR \fIcmd\fR
   311    311   .sp
   312    312   \fBttrace::preload\fR \fIcmd\fR
   313    313   .sp
   314    314   .BE
   315    315   .SH DESCRIPTION
   316    316   This package creates a framework for on-demand replication of the
   317         -interpreter state accross threads in an multithreading application\&.
          317  +interpreter state across threads in an multithreading application\&.
   318    318   It relies on the mechanics of Tcl command tracing and the Tcl
   319    319   \fBunknown\fR command and mechanism\&.
   320    320   .PP
   321    321   The package requires Tcl threading extension but can be alternatively
   322    322   used stand-alone within the AOLserver, a scalable webserver from
   323    323   America Online\&.
   324    324   .PP
................................................................................
   325    325   In a nutshell, a short sample illustrating the usage of the ttrace
   326    326   with the Tcl threading extension:
   327    327   .CS
   328    328   
   329    329   
   330    330   
   331    331       % package require Ttrace
   332         -    2\&.8\&.0
          332  +    2\&.8\&.2
   333    333   
   334    334       % set t1 [thread::create {package require Ttrace; thread::wait}]
   335    335       tid0x1802800
   336    336   
   337    337       % ttrace::eval {proc test args {return test-[thread::id]}}
   338    338       % thread::send $t1 test
   339    339       test-tid0x1802800
................................................................................
   366    366   the extension are automatically updated\&. If the command execution
   367    367   resulted in Tcl error, no state propagation takes place\&.
   368    368   .sp
   369    369   This is the most important user-level command of the package as
   370    370   it wraps most of the commands described below\&. This greatly
   371    371   simplifies things, because user need to learn just this (one)
   372    372   command in order to effectively use the package\&. Other commands,
   373         -as desribed below, are included mostly for the sake of completeness\&.
          373  +as described below, are included mostly for the sake of completeness\&.
   374    374   .TP
   375    375   \fBttrace::enable\fR
   376    376   Activates all registered callbacks in the framework
   377    377   and starts a new trace epoch\&. The trace epoch encapsulates all
   378    378   changes done to the interpreter during the time traces are activated\&.
   379    379   .TP
   380    380   \fBttrace::disable\fR
................................................................................
   387    387   .TP
   388    388   \fBttrace::update\fR ?epoch?
   389    389   Used to refresh the state of the interpreter to match the optional
   390    390   trace ?epoch?\&. If the optional ?epoch? is not given, it takes
   391    391   the most recent trace epoch\&.
   392    392   .TP
   393    393   \fBttrace::getscript\fR
   394         -Returns a synthetized Tcl script which may be sourced in any interpreter\&.
          394  +Returns a synthesized Tcl script which may be sourced in any interpreter\&.
   395    395   This script sets the stage for the Tcl \fBunknown\fR command so it can
   396    396   load traced resources from the in-memory database\&. Normally, this command
   397    397   is automatically invoked by other higher-level commands like
   398    398   \fBttrace::eval\fR and \fBttrace::update\fR\&.
   399    399   .PP
   400    400   .SH "CALLBACK COMMANDS"
   401    401   A word upfront: the package already includes callbacks for tracing
   402    402   following Tcl commands: \fBproc\fR, \fBnamespace\fR, \fBvariable\fR,
   403         -\fBload\fR, and \fBrename\fR\&. Additionaly, a set of callbacks for
   404         -tracing resources (object, clasess) for the XOTcl v1\&.3\&.8+, an
          403  +\fBload\fR, and \fBrename\fR\&. Additionally, a set of callbacks for
          404  +tracing resources (object, classes) for the XOTcl v1\&.3\&.8+, an
   405    405   OO-extension to Tcl, is also provided\&.
   406    406   This gives a solid base for solving most of the real-life needs and
   407    407   serves as an example for people wanting to customize the package
   408    408   to cover their specific needs\&.
   409    409   .PP
   410    410   Below, you can find commands for registering callbacks in the
   411    411   framework and for writing callback scripts\&. These callbacks are
................................................................................
   488    488   This way, users can update just one interpreter (master) in one
   489    489   thread and replicate that interpreter state (or part of it) to other
   490    490   threads/interpreters in the process\&.
   491    491   .PP
   492    492   Immediate benefit of such approach is the much smaller memory footprint
   493    493   of the application and much faster thread creation\&. By not actually
   494    494   loading all necessary procedures (and other resources) in every thread
   495         -at the thread initialization time, but by deffering this to the time the
          495  +at the thread initialization time, but by deferring this to the time the
   496    496   resource is actually referenced, significant improvements in both
   497    497   memory consumption and thread initialization time can be achieved\&. Some
   498    498   tests have shown that memory footprint of an multithreading Tcl application
   499    499   went down more than three times and thread startup time was reduced for
   500    500   about 50 times\&. Note that your mileage may vary\&.
   501    501   Other benefits include much finer control about what (and when) gets
   502    502   replicated from the master to other Tcl thread/interpreters\&.
   503    503   .SH "SEE ALSO"
   504    504   thread, tpool, tsv
   505    505   .SH KEYWORDS
   506    506   command tracing, introspection

Changes to doc/thread.man.

   324    324   This command configures various low-level aspects of the thread with
   325    325   ID [arg id] in the similar way as the standard Tcl command
   326    326   [cmd fconfigure] configures some Tcl channel options. Options currently
   327    327   supported are: [option -eventmark] and [option -unwindonerror].
   328    328   
   329    329   [para]
   330    330   
   331         -The [option -eventmark] option, when set, limits the number of
   332         -asynchronously posted scripts to the thread event loop.
   333         -The [cmd {thread::send -async}] command will block until the number
   334         -of pending scripts in the event loop does not drop below the value
   335         -configured with [option -eventmark]. Default value for the
   336         -[option -eventmark] is 0 (zero) which effectively disables the checking,
   337         -i.e. allows for unlimited number of posted scripts.
          331  +When [option -eventmark] is provided with a value greater than 0 (zero), that
          332  +value is the maximum number of asynchronously posted scripts that may be
          333  +pending for the thread.  [cmd {thread::send -async}] blocks until the number of
          334  +pending scripts in the event loop drops below the [option -eventmark] value.
   338    335   
   339    336   [para]
   340    337   
   341         -The [option -unwindonerror] option, when set, causes the
   342         -target thread to unwind if the result of the script processing
   343         -resulted in error. Default value for the [option -unwindonerror]
   344         -is 0 (false), i.e. thread continues to process scripts after one
   345         -of the posted scripts fails.
          338  +When [option -unwindonerror] is provided with a value of true, an error result
          339  +in a script causes the thread to unwind, making it unavailable to evaluate
          340  +additional scripts.
   346    341   
   347    342   
   348    343   [call [cmd thread::transfer] [arg id] [arg channel]]
   349    344   
   350    345   This moves the specified [arg channel] from the current thread
   351    346   and interpreter to the main interpreter of the thread with the
   352    347   given [arg id]. After the move the current interpreter has no

Changes to generic/threadCmd.c.

   859    859   static int
   860    860   ThreadSendObjCmd(dummy, interp, objc, objv)
   861    861       ClientData  dummy;          /* Not used. */
   862    862       Tcl_Interp *interp;         /* Current interpreter. */
   863    863       STRLEN_TYPE objc;           /* Number of arguments. */
   864    864       Tcl_Obj    *const objv[];   /* Argument objects. */
   865    865   {
   866         -    size_t len, vlen = 0;
          866  +    size_t size;
   867    867       int ret, ii = 0, flags = 0;
   868    868       Tcl_ThreadId thrId;
   869    869       const char *script, *arg;
   870    870       Tcl_Obj *var = NULL;
   871    871   
   872    872       ThreadClbkData *clbkPtr = NULL;
   873    873       ThreadSendData *sendPtr = NULL;
................................................................................
   901    901           return TCL_ERROR;
   902    902       }
   903    903       if (++ii >= objc) {
   904    904           goto usage;
   905    905       }
   906    906   
   907    907       script = Tcl_GetString(objv[ii]);
   908         -    len = objv[ii]->length;
          908  +    size = objv[ii]->length+1;
   909    909       if (++ii < objc) {
   910    910           var = objv[ii];
   911         -        vlen = objv[ii]->length;
   912    911       }
   913    912       if (var && (flags & THREAD_SEND_WAIT) == 0) {
          913  +        const char *varName = Tcl_GetString(var);
          914  +        size_t vsize = var->length + 1;
          915  +
   914    916           if (thrId == Tcl_GetCurrentThread()) {
   915    917               /*
   916    918                * FIXME: Do something for callbacks to self
   917    919                */
   918    920               Tcl_SetObjResult(interp, Tcl_NewStringObj("can't notify self", TCL_STRLEN));
   919    921               return TCL_ERROR;
   920    922           }
................................................................................
   926    928            */
   927    929   
   928    930           clbkPtr = (ThreadClbkData*)ckalloc(sizeof(ThreadClbkData));
   929    931           clbkPtr->execProc   = ThreadClbkSetVar;
   930    932           clbkPtr->freeProc   = threadSendFree;
   931    933           clbkPtr->interp     = interp;
   932    934           clbkPtr->threadId   = Tcl_GetCurrentThread();
   933         -        clbkPtr->clientData = (ClientData)strcpy(ckalloc(1+vlen), Tcl_GetString(var));
          935  +        clbkPtr->clientData = (ClientData)memcpy(ckalloc(vsize), varName, vsize);
   934    936       }
   935    937   
   936    938       /*
   937    939        * Prepare job record for the target thread
   938    940        */
   939    941   
   940    942       sendPtr = (ThreadSendData*)ckalloc(sizeof(ThreadSendData));
   941    943       sendPtr->interp     = NULL; /* Signal to use thread main interp */
   942    944       sendPtr->execProc   = ThreadSendEval;
   943    945       sendPtr->freeProc   = threadSendFree;
   944         -    sendPtr->clientData = (ClientData)strcpy(ckalloc(1+len), script);
          946  +    sendPtr->clientData = (ClientData)memcpy(ckalloc(size), script, size);
   945    947   
   946    948       ret = ThreadSend(interp, thrId, sendPtr, clbkPtr, flags);
   947    949   
   948    950       if (var && (flags & THREAD_SEND_WAIT)) {
   949    951   
   950    952           /*
   951    953            * Leave job's result in passed variable
................................................................................
   988    990   ThreadBroadcastObjCmd(dummy, interp, objc, objv)
   989    991       ClientData  dummy;          /* Not used. */
   990    992       Tcl_Interp *interp;         /* Current interpreter. */
   991    993       STRLEN_TYPE objc;           /* Number of arguments. */
   992    994       Tcl_Obj    *const objv[];   /* Argument objects. */
   993    995   {
   994    996       int ii, nthreads;
   995         -    size_t len;
          997  +    size_t size;
   996    998       const char *script;
   997    999       Tcl_ThreadId *thrIdArray;
   998   1000       ThreadSendData *sendPtr, job;
   999   1001   
  1000   1002       Init(interp);
  1001   1003   
  1002   1004       if (objc != 2) {
  1003   1005           Tcl_WrongNumArgs(interp, 1, objv, "script");
  1004   1006           return TCL_ERROR;
  1005   1007       }
  1006   1008   
  1007   1009       script = Tcl_GetString(objv[1]);
  1008         -    len = objv[1]->length;
         1010  +    size = objv[1]->length + 1;
  1009   1011   
  1010   1012       /*
  1011   1013        * Get the list of known threads. Note that this one may
  1012   1014        * actually change (thread may exit or otherwise cease to
  1013   1015        * exist) while we circle in the loop below. We really do
  1014   1016        * not care about that here since we don't return any
  1015   1017        * script results to the caller.
................................................................................
  1040   1042   
  1041   1043       for (ii = 0; ii < nthreads; ii++) {
  1042   1044           if (thrIdArray[ii] == Tcl_GetCurrentThread()) {
  1043   1045               continue; /* Do not broadcast self */
  1044   1046           }
  1045   1047           sendPtr  = (ThreadSendData*)ckalloc(sizeof(ThreadSendData));
  1046   1048           *sendPtr = job;
  1047         -        sendPtr->clientData = (ClientData)strcpy(ckalloc(1+len), script);
         1049  +        sendPtr->clientData = (ClientData)memcpy(ckalloc(size), script, size);
  1048   1050           ThreadSend(interp, thrIdArray[ii], sendPtr, NULL, THREAD_SEND_HEAD);
  1049   1051       }
  1050   1052   
  1051   1053       ckfree((char*)thrIdArray);
  1052   1054       Tcl_ResetResult(interp);
  1053   1055   
  1054   1056       return TCL_OK;
................................................................................
  3159   3161   
  3160   3162   static void
  3161   3163   ThreadSetResult(interp, code, resultPtr)
  3162   3164       Tcl_Interp *interp;
  3163   3165       int code;
  3164   3166       ThreadEventResult *resultPtr;
  3165   3167   {
  3166         -    size_t reslen;
         3168  +    size_t size;
  3167   3169       const char *errorCode, *errorInfo, *result;
  3168   3170   
  3169   3171       if (interp == NULL) {
  3170   3172           code      = TCL_ERROR;
  3171   3173           errorInfo = "";
  3172   3174           errorCode = "THREAD";
  3173   3175           result    = "no target interp!";
  3174         -        reslen    = strlen(result);
  3175         -        resultPtr->result = (reslen) ?
  3176         -            strcpy(ckalloc(1+reslen), result) : threadEmptyResult;
         3176  +        size    = strlen(result);
         3177  +        resultPtr->result = (size) ?
         3178  +            memcpy(ckalloc(1+size), result, 1+size) : threadEmptyResult;
  3177   3179       } else {
  3178   3180           result = Tcl_GetString(Tcl_GetObjResult(interp));
  3179         -        reslen = Tcl_GetObjResult(interp)->length;
  3180         -        resultPtr->result = (reslen) ?
  3181         -            strcpy(ckalloc(1+reslen), result) : threadEmptyResult;
         3181  +        size = Tcl_GetObjResult(interp)->length;
         3182  +        resultPtr->result = (size) ?
         3183  +            memcpy(ckalloc(1+size), result, 1+size) : threadEmptyResult;
  3182   3184           if (code == TCL_ERROR) {
  3183   3185               errorCode = Tcl_GetVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY);
  3184   3186               errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
  3185   3187           } else {
  3186   3188               errorCode = NULL;
  3187   3189               errorInfo = NULL;
  3188   3190           }
  3189   3191       }
  3190   3192   
  3191   3193       resultPtr->code = code;
  3192   3194   
  3193   3195       if (errorCode != NULL) {
  3194         -        resultPtr->errorCode = ckalloc(1+strlen(errorCode));
  3195         -        strcpy(resultPtr->errorCode, errorCode);
         3196  +        size = strlen(errorCode) + 1;
         3197  +        resultPtr->errorCode = memcpy(ckalloc(size), errorCode, size);
  3196   3198       } else {
  3197   3199           resultPtr->errorCode = NULL;
  3198   3200       }
  3199   3201       if (errorInfo != NULL) {
  3200         -        resultPtr->errorInfo = ckalloc(1+strlen(errorInfo));
  3201         -        strcpy(resultPtr->errorInfo, errorInfo);
         3202  +        size = strlen(errorInfo) + 1;
         3203  +        resultPtr->errorInfo = memcpy(ckalloc(size), errorInfo, size);
  3202   3204       } else {
  3203   3205           resultPtr->errorInfo = NULL;
  3204   3206       }
  3205   3207   }
  3206   3208   
  3207   3209   /*
  3208   3210    *----------------------------------------------------------------------
................................................................................
  3446   3448               code = TCL_OK; /* Return success. */
  3447   3449           }
  3448   3450       }
  3449   3451       if (resultPtr) {
  3450   3452           Tcl_MutexLock(&threadMutex);
  3451   3453           resultPtr->resultCode = code;
  3452   3454           if (msg != NULL) {
  3453         -            resultPtr->resultMsg = (char*)ckalloc(1+strlen (msg));
  3454         -            strcpy (resultPtr->resultMsg, msg);
         3455  +            size_t size = strlen(msg)+1;
         3456  +            resultPtr->resultMsg = memcpy(ckalloc(size), msg, size);
  3455   3457           }
  3456   3458           Tcl_ConditionNotify(&resultPtr->done);
  3457   3459           Tcl_MutexUnlock(&threadMutex);
  3458   3460       }
  3459   3461   
  3460   3462       return 1;
  3461   3463   }

Changes to generic/threadSvListCmd.c.

    33     33   static Tcl_ObjCmdProc SvLindexObjCmd;    /* lindex      */
    34     34   static Tcl_ObjCmdProc SvLinsertObjCmd;   /* linsert     */
    35     35   static Tcl_ObjCmdProc SvLrangeObjCmd;    /* lrange      */
    36     36   static Tcl_ObjCmdProc SvLsearchObjCmd;   /* lsearch     */
    37     37   static Tcl_ObjCmdProc SvLsetObjCmd;      /* lset        */
    38     38   
    39     39   /*
    40         - * These two are copied verbatim from the tclUtil.c
           40  + * This is copied verbatim from the tclUtil.c
    41     41    * since not found in the public stubs table.
    42         - * I was just too lazy to rewrite them from scratch.
           42  + * I was just too lazy to rewrite it from scratch.
    43     43    */
    44     44   
    45         -static int SvCheckBadOctal(Tcl_Interp*, const char *);
    46     45   static int SvGetIntForIndex(Tcl_Interp*,  Tcl_Obj *, int, int*);
    47     46   
    48     47   /*
    49     48    * Inefficient list duplicator function which,
    50     49    * however, produces deep list copies, unlike
    51     50    * the original, which just makes shallow copies.
    52     51    */
................................................................................
   915    914   
   916    915       ckfree((char*)newObjList);
   917    916   }
   918    917   
   919    918   /*
   920    919    *-----------------------------------------------------------------------------
   921    920    *
   922         - * SvCheckBadOctal --
   923         - *
   924         - *  Exact copy from the TclCheckBadOctal found in tclUtil.c
   925         - *  since this is not in the stubs table.
   926         - *
   927         - *-----------------------------------------------------------------------------
   928         - */
   929         -
   930         -static int
   931         -SvCheckBadOctal(interp, value)
   932         -    Tcl_Interp *interp;     /* Interpreter to use for error reporting.
   933         -                             * If NULL, then no error message is left
   934         -                             * after errors. */
   935         -    const char *value;      /* String to check. */
   936         -{
   937         -    register const char *p = value;
   938         -
   939         -    /*
   940         -     * A frequent mistake is invalid octal values due to an unwanted
   941         -     * leading zero. Try to generate a meaningful error message.
   942         -     */
   943         -
   944         -    while (isspace((unsigned char)(*p))) { /* INTL: ISO space. */
   945         -        p++;
   946         -    }
   947         -    if (*p == '+' || *p == '-') {
   948         -        p++;
   949         -    }
   950         -    if (*p == '0') {
   951         -        while (isdigit((unsigned char)(*p))) { /* INTL: digit. */
   952         -            p++;
   953         -        }
   954         -        while (isspace((unsigned char)(*p))) { /* INTL: ISO space. */
   955         -            p++;
   956         -        }
   957         -        if (*p == '\0') {
   958         -            /* Reached end of string */
   959         -            if (interp != NULL) {
   960         -                Tcl_AppendResult(interp, " (looks like invalid octal number)",
   961         -                        (char *) NULL);
   962         -            }
   963         -            return 1;
   964         -        }
   965         -    }
   966         -    return 0;
   967         -}
   968         -
   969         -/*
   970         - *-----------------------------------------------------------------------------
   971         - *
   972    921    * SvGetIntForIndex --
   973    922    *
   974    923    *  Exact copy from the TclGetIntForIndex found in tclUtil.c
   975    924    *  since this is not in the stubs table.
   976    925    *
   977    926    *-----------------------------------------------------------------------------
   978    927    */
................................................................................
  1016    965           *indexPtr = endValue + offset;
  1017    966       } else {
  1018    967     intforindex_error:
  1019    968           if (interp != NULL) {
  1020    969               Tcl_ResetResult(interp);
  1021    970               Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad index \"",
  1022    971                       bytes, "\": must be integer or end?-integer?",(char*)NULL);
  1023         -            SvCheckBadOctal(interp, bytes);
  1024    972           }
  1025    973           return TCL_ERROR;
  1026    974       }
  1027    975       return TCL_OK;
  1028    976   }
  1029    977   
  1030    978   /*

Changes to tests/thread.test.

   249    249       set five [thread::send $tid {set x}]
   250    250       ThreadReap
   251    251       set five
   252    252   } {5}
   253    253   
   254    254   test thread-11.7 {thread::send - async send with event-loop wait} {
   255    255       ThreadReap
          256  +    set res {}
   256    257       set tid [thread::create]
   257    258       thread::send -async $tid {set x 5} five
   258    259       vwait five
          260  +    lappend res $five; set five {}
          261  +    thread::send -async $tid {set x 5} [binary format cccc 0x66 0x69 0x76 0x65]; # five as byte array without str-rep.
          262  +    vwait five
          263  +    lappend res $five; set five {}
   259    264       ThreadReap
   260         -    set five
   261         -} {5}
          265  +    set res
          266  +} {5 5}
          267  +
          268  +test thread-11.7.1 {thread::send - sync send with var} {
          269  +    ThreadReap
          270  +    set res {}
          271  +    set tid [thread::create]
          272  +    thread::send $tid {set x 5} five
          273  +    lappend res $five; set five {}
          274  +    thread::send $tid {set x 5} [binary format cccc 0x66 0x69 0x76 0x65]; # five as byte array without str-rep.
          275  +    lappend res $five; set five {}
          276  +    ThreadReap
          277  +    set res
          278  +} {5 5}
   262    279   
   263    280   test thread-11.8 {thread::send - send to self directly} {
   264    281       thread::send [thread::id] {set x 5} five
   265    282       set five
   266    283   } {5}
   267    284   
   268    285   test thread-11.9 {thread::send - send to self asynchronously} {