Import Tcl 8.6.12
This commit is contained in:
35
pkgs/thread2.8.7/doc/format.tcl
Normal file
35
pkgs/thread2.8.7/doc/format.tcl
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/usr/local/bin/tclsh
|
||||
set mydir [file dirname [info script]]
|
||||
lappend auto_path /usr/local/lib
|
||||
package req doctools
|
||||
doctools::new dt
|
||||
set wd [pwd]
|
||||
cd $mydir
|
||||
file rename html htm
|
||||
set code [catch {
|
||||
set f [open man.macros]
|
||||
set m [read $f]
|
||||
close $f
|
||||
foreach file [glob -nocomplain *.man] {
|
||||
set xx [file root $file]
|
||||
set f [open $xx.man]
|
||||
set t [read $f]
|
||||
close $f
|
||||
foreach {fmt ext dir} {nroff n man html html htm} {
|
||||
dt configure -format $fmt
|
||||
set o [dt format $t]
|
||||
set f [open $dir/$xx.$ext w]
|
||||
if {$fmt == "nroff"} {
|
||||
set o [string map [list {.so man.macros} $m] $o]
|
||||
}
|
||||
puts $f $o
|
||||
close $f
|
||||
}
|
||||
}
|
||||
} err]
|
||||
file rename htm html
|
||||
cd $wd
|
||||
if {$code} {
|
||||
error $err
|
||||
}
|
||||
exit 0
|
||||
604
pkgs/thread2.8.7/doc/html/thread.html
Normal file
604
pkgs/thread2.8.7/doc/html/thread.html
Normal file
@@ -0,0 +1,604 @@
|
||||
|
||||
<html><head>
|
||||
<title>thread - Tcl Threading</title>
|
||||
<style type="text/css"><!--
|
||||
HTML {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
BODY {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
DIV.doctools {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
DIV.doctools H1,DIV.doctools H2 {
|
||||
margin-left: -5%;
|
||||
}
|
||||
H1, H2, H3, H4 {
|
||||
margin-top: 1em;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
color: #005A9C;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
}
|
||||
H1.doctools_title {
|
||||
text-align: center;
|
||||
}
|
||||
UL,OL {
|
||||
margin-right: 0em;
|
||||
margin-top: 3pt;
|
||||
margin-bottom: 3pt;
|
||||
}
|
||||
UL LI {
|
||||
list-style: disc;
|
||||
}
|
||||
OL LI {
|
||||
list-style: decimal;
|
||||
}
|
||||
DT {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
|
||||
font: normal 12pt/14pt sans-serif;
|
||||
list-style: none;
|
||||
}
|
||||
LI.doctools_section, LI.doctools_subsection {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
PRE {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
margin: 0%;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0.5ex;
|
||||
padding-left: 1ex;
|
||||
padding-right: 1ex;
|
||||
width: 100%;
|
||||
}
|
||||
PRE.doctools_example {
|
||||
color: black;
|
||||
background: #f5dcb3;
|
||||
border: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements LI, UL.doctools_syntax LI {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
DIV.doctools_synopsis {
|
||||
color: black;
|
||||
background: #80ffff;
|
||||
border: 1px solid black;
|
||||
font-family: serif;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
UL.doctools_syntax {
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements {
|
||||
margin-bottom: 1em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
--></style>
|
||||
</head>
|
||||
<! -- Generated from file '' by tcllib/doctools with format 'html'
|
||||
-->
|
||||
<! -- thread.n
|
||||
-->
|
||||
<body><div class="doctools">
|
||||
<h1 class="doctools_title">thread(n) 2.8 "Tcl Threading"</h1>
|
||||
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
|
||||
<p>thread - Extension for script access to Tcl threading</p>
|
||||
</div>
|
||||
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
|
||||
<ul class="doctools_toc">
|
||||
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
|
||||
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
|
||||
<li class="doctools_section"><a href="#section1">Description</a></li>
|
||||
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section3">DISCUSSION</a></li>
|
||||
<li class="doctools_section"><a href="#see-also">See Also</a></li>
|
||||
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
|
||||
<div class="doctools_synopsis">
|
||||
<ul class="doctools_requirements">
|
||||
<li>package require <b class="pkgname">Tcl 8.4</b></li>
|
||||
<li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li>
|
||||
</ul>
|
||||
<ul class="doctools_syntax">
|
||||
<li><a href="#1"><b class="cmd">thread::create</b> <span class="opt">?-joinable?</span> <span class="opt">?-preserved?</span> <span class="opt">?script?</span></a></li>
|
||||
<li><a href="#2"><b class="cmd">thread::preserve</b> <span class="opt">?id?</span></a></li>
|
||||
<li><a href="#3"><b class="cmd">thread::release</b> <span class="opt">?-wait?</span> <span class="opt">?id?</span></a></li>
|
||||
<li><a href="#4"><b class="cmd">thread::id</b></a></li>
|
||||
<li><a href="#5"><b class="cmd">thread::errorproc</b> <span class="opt">?procname?</span></a></li>
|
||||
<li><a href="#6"><b class="cmd">thread::cancel</b> <span class="opt">?-unwind?</span> <i class="arg">id</i> <span class="opt">?result?</span></a></li>
|
||||
<li><a href="#7"><b class="cmd">thread::unwind</b></a></li>
|
||||
<li><a href="#8"><b class="cmd">thread::exit</b> <span class="opt">?status?</span></a></li>
|
||||
<li><a href="#9"><b class="cmd">thread::names</b></a></li>
|
||||
<li><a href="#10"><b class="cmd">thread::exists</b> <i class="arg">id</i></a></li>
|
||||
<li><a href="#11"><b class="cmd">thread::send</b> <span class="opt">?-async?</span> <span class="opt">?-head?</span> <i class="arg">id</i> <i class="arg">script</i> <span class="opt">?varname?</span></a></li>
|
||||
<li><a href="#12"><b class="cmd">thread::broadcast</b> <i class="arg">script</i></a></li>
|
||||
<li><a href="#13"><b class="cmd">thread::wait</b></a></li>
|
||||
<li><a href="#14"><b class="cmd">thread::eval</b> <span class="opt">?-lock mutex?</span> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li>
|
||||
<li><a href="#15"><b class="cmd">thread::join</b> <i class="arg">id</i></a></li>
|
||||
<li><a href="#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></li>
|
||||
<li><a href="#17"><b class="cmd">thread::transfer</b> <i class="arg">id</i> <i class="arg">channel</i></a></li>
|
||||
<li><a href="#18"><b class="cmd">thread::detach</b> <i class="arg">channel</i></a></li>
|
||||
<li><a href="#19"><b class="cmd">thread::attach</b> <i class="arg">channel</i></a></li>
|
||||
<li><a href="#20"><b class="cmd">thread::mutex</b></a></li>
|
||||
<li><a href="#21"><b class="cmd">thread::mutex</b> <b class="method">create</b> <span class="opt">?-recursive?</span></a></li>
|
||||
<li><a href="#22"><b class="cmd">thread::mutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#23"><b class="cmd">thread::mutex</b> <b class="method">lock</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#24"><b class="cmd">thread::mutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#25"><b class="cmd">thread::rwmutex</b></a></li>
|
||||
<li><a href="#26"><b class="cmd">thread::rwmutex</b> <b class="method">create</b></a></li>
|
||||
<li><a href="#27"><b class="cmd">thread::rwmutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#28"><b class="cmd">thread::rwmutex</b> <b class="method">rlock</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#29"><b class="cmd">thread::rwmutex</b> <b class="method">wlock</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#30"><b class="cmd">thread::rwmutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></li>
|
||||
<li><a href="#31"><b class="cmd">thread::cond</b></a></li>
|
||||
<li><a href="#32"><b class="cmd">thread::cond</b> <b class="method">create</b></a></li>
|
||||
<li><a href="#33"><b class="cmd">thread::cond</b> <b class="method">destroy</b> <i class="arg">cond</i></a></li>
|
||||
<li><a href="#34"><b class="cmd">thread::cond</b> <b class="method">notify</b> <i class="arg">cond</i></a></li>
|
||||
<li><a href="#35"><b class="cmd">thread::cond</b> <b class="method">wait</b> <i class="arg">cond</i> <i class="arg">mutex</i> <span class="opt">?ms?</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
|
||||
<p>The <b class="package">thread</b> extension creates threads that contain Tcl
|
||||
interpreters, and it lets you send scripts to those threads for
|
||||
evaluation.
|
||||
Additionaly, it provides script-level access to basic thread
|
||||
synchronization primitives, like mutexes and condition variables.</p>
|
||||
</div>
|
||||
<div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2>
|
||||
<p>This section describes commands for creating and destroying threads
|
||||
and sending scripts to threads for evaluation.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<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>
|
||||
<dd><p>This command creates a thread that contains a Tcl interpreter.
|
||||
The Tcl interpreter either evaluates the optional <b class="option">script</b>, if
|
||||
specified, or it waits in the event loop for scripts that arrive via
|
||||
the <b class="cmd">thread::send</b> command. The result, if any, of the
|
||||
optional <b class="option">script</b> is never returned to the caller.
|
||||
The result of <b class="cmd">thread::create</b> is the ID of the thread. This is
|
||||
the opaque handle which identifies the newly created thread for
|
||||
all other package commands. The handle of the thread goes out of scope
|
||||
automatically when thread is marked for exit
|
||||
(see the <b class="cmd">thread::release</b> command below).</p>
|
||||
<p>If the optional <b class="option">script</b> argument contains the <b class="cmd">thread::wait</b>
|
||||
command the thread will enter into the event loop. If such command is not
|
||||
found in the <b class="option">script</b> the thread will run the <b class="option">script</b> to
|
||||
the end and exit. In that case, the handle may be safely ignored since it
|
||||
refers to a thread which does not exists any more at the time when the
|
||||
command returns.</p>
|
||||
<p>Using flag <b class="option">-joinable</b> it is possible to create a joinable
|
||||
thread, i.e. one upon whose exit can be waited upon by using
|
||||
<b class="cmd">thread::join</b> command.
|
||||
Note that failure to join a thread created with <b class="option">-joinable</b> flag
|
||||
results in resource and memory leaks.</p>
|
||||
<p>Threads created by the <b class="cmd">thread::create</b> cannot be destroyed
|
||||
forcefully. Consequently, there is no corresponding thread destroy
|
||||
command. A thread may only be released using the <b class="cmd">thread::release</b>
|
||||
and if its internal reference count drops to zero, the thread is
|
||||
marked for exit. This kicks the thread out of the event loop
|
||||
servicing and the thread continues to execute commands passed in
|
||||
the <b class="option">script</b> argument, following the <b class="cmd">thread::wait</b>
|
||||
command. If this was the last command in the script, as usualy the
|
||||
case, the thread will exit.</p>
|
||||
<p>It is possible to create a situation in which it may be impossible
|
||||
to terminate the thread, for example by putting some endless loop
|
||||
after the <b class="cmd">thread::wait</b> or entering the event loop again by
|
||||
doing an vwait-type of command. In such cases, the thread may never
|
||||
exit. This is considered to be a bad practice and should be avoided
|
||||
if possible. This is best illustrated by the example below:</p>
|
||||
<pre class="doctools_example">
|
||||
# You should never do ...
|
||||
set tid [thread::create {
|
||||
package require Http
|
||||
thread::wait
|
||||
vwait forever ; # <-- this!
|
||||
}]
|
||||
</pre>
|
||||
<p>The thread created in the above example will never be able to exit.
|
||||
After it has been released with the last matching <b class="cmd">thread::release</b>
|
||||
call, the thread will jump out of the <b class="cmd">thread::wait</b> and continue
|
||||
to execute commands following. It will enter <b class="cmd">vwait</b> command and
|
||||
wait endlessly for events. There is no way one can terminate such thread,
|
||||
so you wouldn't want to do this!</p>
|
||||
<p>Each newly created has its internal reference counter set to 0 (zero),
|
||||
i.e. it is unreserved. This counter gets incremented by a call to
|
||||
<b class="cmd">thread::preserve</b> and decremented by a call to <b class="cmd">thread::release</b>
|
||||
command. These two commands implement simple but effective thread
|
||||
reservation system and offer predictable and controllable thread
|
||||
termination capabilities. It is however possible to create initialy
|
||||
preserved threads by using flag <b class="option">-preserved</b> of the
|
||||
<b class="cmd">thread::create</b> command. Threads created with this flag have the
|
||||
initial value of the reference counter of 1 (one), and are thus
|
||||
initially marked reserved.</p></dd>
|
||||
<dt><a name="2"><b class="cmd">thread::preserve</b> <span class="opt">?id?</span></a></dt>
|
||||
<dd><p>This command increments the thread reference counter. Each call
|
||||
to this command increments the reference counter by one (1).
|
||||
Command returns the value of the reference counter after the increment.
|
||||
If called with the optional thread <b class="option">id</b>, the command preserves
|
||||
the given thread. Otherwise the current thread is preserved.</p>
|
||||
<p>With reference counting, one can implement controlled access to a
|
||||
shared Tcl thread. By incrementing the reference counter, the
|
||||
caller signalizes that he/she wishes to use the thread for a longer
|
||||
period of time. By decrementing the counter, caller signalizes that
|
||||
he/she has finished using the thread.</p></dd>
|
||||
<dt><a name="3"><b class="cmd">thread::release</b> <span class="opt">?-wait?</span> <span class="opt">?id?</span></a></dt>
|
||||
<dd><p>This command decrements the thread reference counter. Each call to
|
||||
this command decrements the reference counter by one (1).
|
||||
If called with the optional thread <b class="option">id</b>, the command releases
|
||||
the given thread. Otherwise, the current thread is released.
|
||||
Command returns the value of the reference counter after the decrement.
|
||||
When the reference counter reaches zero (0), the target thread is
|
||||
marked for termination. You should not reference the thread after the
|
||||
<b class="cmd">thread::release</b> command returns zero or negative integer.
|
||||
The handle of the thread goes out of scope and should not be used any
|
||||
more. Any following reference to the same thread handle will result
|
||||
in Tcl error.</p>
|
||||
<p>Optional flag <b class="option">-wait</b> instructs the caller thread to wait for
|
||||
the target thread to exit, if the effect of the command would result
|
||||
in termination of the target thread, i.e. if the return result would
|
||||
be zero (0). Without the flag, the caller thread does not wait for
|
||||
the target thread to exit. Care must be taken when using the
|
||||
<b class="option">-wait</b>, since this may block the caller thread indefinitely.
|
||||
This option has been implemented for some special uses of the extension
|
||||
and is deprecated for regular use. Regular users should create joinable
|
||||
threads by using the <b class="option">-joinable</b> option of the <b class="cmd">thread::create</b>
|
||||
command and the <b class="cmd">thread::join</b> to wait for thread to exit.</p></dd>
|
||||
<dt><a name="4"><b class="cmd">thread::id</b></a></dt>
|
||||
<dd><p>This command returns the ID of the current thread.</p></dd>
|
||||
<dt><a name="5"><b class="cmd">thread::errorproc</b> <span class="opt">?procname?</span></a></dt>
|
||||
<dd><p>This command sets a handler for errors that occur in scripts sent
|
||||
asynchronously, using the <b class="option">-async</b> flag of the
|
||||
<b class="cmd">thread::send</b> command, to other threads. If no handler
|
||||
is specified, the current handler is returned. The empty string
|
||||
resets the handler to default (unspecified) value.
|
||||
An uncaught error in a thread causes an error message to be sent
|
||||
to the standard error channel. This default reporting scheme can
|
||||
be changed by registering a procedure which is called to report
|
||||
the error. The <i class="arg">procname</i> is called in the interpreter that
|
||||
invoked the <b class="cmd">thread::errorproc</b> command. The <i class="arg">procname</i>
|
||||
is called like this:</p>
|
||||
<pre class="doctools_example">
|
||||
myerrorproc thread_id errorInfo
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><a name="6"><b class="cmd">thread::cancel</b> <span class="opt">?-unwind?</span> <i class="arg">id</i> <span class="opt">?result?</span></a></dt>
|
||||
<dd><p>This command requires Tcl version 8.6 or higher.</p>
|
||||
<p>Cancels the script being evaluated in the thread given by the <i class="arg">id</i>
|
||||
parameter. Without the <b class="option">-unwind</b> switch the evaluation stack for
|
||||
the interpreter is unwound until an enclosing catch command is found or
|
||||
there are no further invocations of the interpreter left on the call
|
||||
stack. With the <b class="option">-unwind</b> switch the evaluation stack for the
|
||||
interpreter is unwound without regard to any intervening catch command
|
||||
until there are no further invocations of the interpreter left on the
|
||||
call stack. If <i class="arg">result</i> is present, it will be used as the error
|
||||
message string; otherwise, a default error message string will be used.</p></dd>
|
||||
<dt><a name="7"><b class="cmd">thread::unwind</b></a></dt>
|
||||
<dd><p>Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with <b class="cmd">thread::preserve</b> and
|
||||
<b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::unwind</b>
|
||||
command will dissapear in some future major release of the extension.</p>
|
||||
<p>This command stops a prior <b class="cmd">thread::wait</b> command. Execution of
|
||||
the script passed to newly created thread will continue from the
|
||||
<b class="cmd">thread::wait</b> command. If <b class="cmd">thread::wait</b> was the last command
|
||||
in the script, the thread will exit. The command returns empty result
|
||||
but may trigger Tcl error with the message "target thread died" in some
|
||||
situations.</p></dd>
|
||||
<dt><a name="8"><b class="cmd">thread::exit</b> <span class="opt">?status?</span></a></dt>
|
||||
<dd><p>Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with <b class="cmd">thread::preserve</b> and
|
||||
<b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::exit</b>
|
||||
command will dissapear in some future major release of the extension.</p>
|
||||
<p>This command forces a thread stuck in the <b class="cmd">thread::wait</b> command to
|
||||
unconditionaly exit. The thread's exit status defaults to 666 and can be
|
||||
specified using the optional <i class="arg">status</i> argument. The execution of
|
||||
<b class="cmd">thread::exit</b> command is guaranteed to leave the program memory in the
|
||||
unconsistent state, produce memory leaks and otherwise affect other subsytem(s)
|
||||
of the Tcl application in an unpredictable manner. The command returns empty
|
||||
result but may trigger Tcl error with the message "target thread died" in some
|
||||
situations.</p></dd>
|
||||
<dt><a name="9"><b class="cmd">thread::names</b></a></dt>
|
||||
<dd><p>This command returns a list of thread IDs. These are only for
|
||||
threads that have been created via <b class="cmd">thread::create</b> command.
|
||||
If your application creates other threads at the C level, they
|
||||
are not reported by this command.</p></dd>
|
||||
<dt><a name="10"><b class="cmd">thread::exists</b> <i class="arg">id</i></a></dt>
|
||||
<dd><p>Returns true (1) if thread given by the <i class="arg">id</i> parameter exists,
|
||||
false (0) otherwise. This applies only for threads that have
|
||||
been created via <b class="cmd">thread::create</b> command.</p></dd>
|
||||
<dt><a name="11"><b class="cmd">thread::send</b> <span class="opt">?-async?</span> <span class="opt">?-head?</span> <i class="arg">id</i> <i class="arg">script</i> <span class="opt">?varname?</span></a></dt>
|
||||
<dd><p>This command passes a <i class="arg">script</i> to another thread and, optionally,
|
||||
waits for the result. If the <b class="option">-async</b> flag is specified, the
|
||||
command does not wait for the result and it returns empty string.
|
||||
The target thread must enter it's event loop in order to receive
|
||||
scripts sent via this command. This is done by default for threads
|
||||
created without a startup script. Threads can enter the event loop
|
||||
explicitly by calling <b class="cmd">thread::wait</b> or any other relevant Tcl/Tk
|
||||
command, like <b class="cmd">update</b>, <b class="cmd">vwait</b>, etc.</p>
|
||||
<p>Optional <b class="option">varname</b> specifies name of the variable to store
|
||||
the result of the <i class="arg">script</i>. Without the <b class="option">-async</b> flag,
|
||||
the command returns the evaluation code, similarily to the standard
|
||||
Tcl <b class="cmd">catch</b> command. If, however, the <b class="option">-async</b> flag is
|
||||
specified, the command returns immediately and caller can later
|
||||
<b class="cmd">vwait</b> on <span class="opt">?varname?</span> to get the result of the passed <i class="arg">script</i></p>
|
||||
<pre class="doctools_example">
|
||||
set t1 [thread::create]
|
||||
set t2 [thread::create]
|
||||
thread::send -async $t1 "set a 1" result
|
||||
thread::send -async $t2 "set b 2" result
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
vwait result
|
||||
}
|
||||
</pre>
|
||||
<p>In the above example, two threads were fed work and both of them were
|
||||
instructed to signalize the same variable "result" in the calling thread.
|
||||
The caller entered the event loop twice to get both results. Note,
|
||||
however, that the order of the received results may vary, depending on
|
||||
the current system load, type of work done, etc, etc.</p>
|
||||
<p>Many threads can simultaneously send scripts to the target thread for
|
||||
execution. All of them are entered into the event queue of the target
|
||||
thread and executed on the FIFO basis, intermingled with optional other
|
||||
events pending in the event queue of the target thread.
|
||||
Using the optional <span class="opt">?-head?</span> switch, scripts posted to the thread's
|
||||
event queue can be placed on the head, instead on the tail of the queue,
|
||||
thus being executed in the LIFO fashion.</p></dd>
|
||||
<dt><a name="12"><b class="cmd">thread::broadcast</b> <i class="arg">script</i></a></dt>
|
||||
<dd><p>This command passes a <i class="arg">script</i> to all threads created by the
|
||||
package for execution. It does not wait for response from any of
|
||||
the threads.</p></dd>
|
||||
<dt><a name="13"><b class="cmd">thread::wait</b></a></dt>
|
||||
<dd><p>This enters the event loop so a thread can receive messages from
|
||||
the <b class="cmd">thread::send</b> command. This command should only be used
|
||||
within the script passed to the <b class="cmd">thread::create</b>. It should
|
||||
be the very last command in the script. If this is not the case,
|
||||
the exiting thread will continue executing the script lines past
|
||||
the <b class="cmd">thread::wait</b> which is usually not what you want and/or
|
||||
expect.</p>
|
||||
<pre class="doctools_example">
|
||||
set t1 [thread::create {
|
||||
#
|
||||
# Do some initialization work here
|
||||
#
|
||||
thread::wait ; # Enter the event loop
|
||||
}]
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><a name="14"><b class="cmd">thread::eval</b> <span class="opt">?-lock mutex?</span> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt>
|
||||
<dd><p>This command concatenates passed arguments and evaluates the
|
||||
resulting script under the mutex protection. If no mutex is
|
||||
specified by using the <span class="opt">?-lock mutex?</span> optional argument,
|
||||
the internal static mutex is used.</p></dd>
|
||||
<dt><a name="15"><b class="cmd">thread::join</b> <i class="arg">id</i></a></dt>
|
||||
<dd><p>This command waits for the thread with ID <i class="arg">id</i> to exit and
|
||||
then returns it's exit code. Errors will be returned for threads
|
||||
which are not joinable or already waited upon by another thread.
|
||||
Upon the join the handle of the thread has gone out of scope and
|
||||
should not be used any more.</p></dd>
|
||||
<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>
|
||||
<dd><p>This command configures various low-level aspects of the thread with
|
||||
ID <i class="arg">id</i> in the similar way as the standard Tcl command
|
||||
<b class="cmd">fconfigure</b> configures some Tcl channel options. Options currently
|
||||
supported are: <b class="option">-eventmark</b> and <b class="option">-unwindonerror</b>.</p>
|
||||
<p>The <b class="option">-eventmark</b> option, when set, limits the number of
|
||||
asynchronously posted scripts to the thread event loop.
|
||||
The <b class="cmd">thread::send -async</b> command will block until the number
|
||||
of pending scripts in the event loop does not drop below the value
|
||||
configured with <b class="option">-eventmark</b>. Default value for the
|
||||
<b class="option">-eventmark</b> is 0 (zero) which effectively disables the checking,
|
||||
i.e. allows for unlimited number of posted scripts.</p>
|
||||
<p>The <b class="option">-unwindonerror</b> option, when set, causes the
|
||||
target thread to unwind if the result of the script processing
|
||||
resulted in error. Default value for the <b class="option">-unwindonerror</b>
|
||||
is 0 (false), i.e. thread continues to process scripts after one
|
||||
of the posted scripts fails.</p></dd>
|
||||
<dt><a name="17"><b class="cmd">thread::transfer</b> <i class="arg">id</i> <i class="arg">channel</i></a></dt>
|
||||
<dd><p>This moves the specified <i class="arg">channel</i> from the current thread
|
||||
and interpreter to the main interpreter of the thread with the
|
||||
given <i class="arg">id</i>. After the move the current interpreter has no
|
||||
access to the channel any more, but the main interpreter of the
|
||||
target thread will be able to use it from now on.
|
||||
The command waits until the other thread has incorporated the
|
||||
channel. Because of this it is possible to deadlock the
|
||||
participating threads by commanding the other through a
|
||||
synchronous <b class="cmd">thread::send</b> to transfer a channel to us.
|
||||
This easily extends into longer loops of threads waiting for
|
||||
each other. Other restrictions: the channel in question must
|
||||
not be shared among multiple interpreters running in the
|
||||
sending thread. This automatically excludes the special channels
|
||||
for standard input, output and error.</p>
|
||||
<p>Due to the internal Tcl core implementation and the restriction on
|
||||
transferring shared channels, one has to take extra measures when
|
||||
transferring socket channels created by accepting the connection
|
||||
out of the <b class="cmd">socket</b> commands callback procedures:</p>
|
||||
<pre class="doctools_example">
|
||||
socket -server _Accept 2200
|
||||
proc _Accept {s ipaddr port} {
|
||||
after idle [list Accept $s $ipaddr $port]
|
||||
}
|
||||
proc Accept {s ipaddr port} {
|
||||
set tid [thread::create]
|
||||
thread::transfer $tid $s
|
||||
}
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><a name="18"><b class="cmd">thread::detach</b> <i class="arg">channel</i></a></dt>
|
||||
<dd><p>This detaches the specified <i class="arg">channel</i> from the current thread and
|
||||
interpreter. After that, the current interpreter has no access to the
|
||||
channel any more. The channel is in the parked state until some other
|
||||
(or the same) thread attaches the channel again with <b class="cmd">thread::attach</b>.
|
||||
Restrictions: same as for transferring shared channels with the
|
||||
<b class="cmd">thread::transfer</b> command.</p></dd>
|
||||
<dt><a name="19"><b class="cmd">thread::attach</b> <i class="arg">channel</i></a></dt>
|
||||
<dd><p>This attaches the previously detached <i class="arg">channel</i> in the
|
||||
current thread/interpreter. For already existing channels,
|
||||
the command does nothing, i.e. it is not an error to attach the
|
||||
same channel more than once. The first operation will actualy
|
||||
perform the operation, while all subsequent operation will just
|
||||
do nothing. Command throws error if the <i class="arg">channel</i> cannot be
|
||||
found in the list of detached channels and/or in the current
|
||||
interpreter.</p></dd>
|
||||
<dt><a name="20"><b class="cmd">thread::mutex</b></a></dt>
|
||||
<dd><p>Mutexes are most common thread synchronization primitives.
|
||||
They are used to synchronize access from two or more threads to one or
|
||||
more shared resources. This command provides script-level access to
|
||||
exclusive and/or recursive mutexes. Exclusive mutexes can be locked
|
||||
only once by one thread, while recursive mutexes can be locked many
|
||||
times by the same thread. For recursive mutexes, number of lock and
|
||||
unlock operations must match, otherwise, the mutex will never be
|
||||
released, which would lead to various deadlock situations.</p>
|
||||
<p>Care has to be taken when using mutexes in an multithreading program.
|
||||
Improper use of mutexes may lead to various deadlock situations,
|
||||
especially when using exclusive mutexes.</p>
|
||||
<p>The <b class="cmd">thread::mutex</b> command supports following subcommands and options:</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="21"><b class="cmd">thread::mutex</b> <b class="method">create</b> <span class="opt">?-recursive?</span></a></dt>
|
||||
<dd><p>Creates the mutex and returns it's opaque handle. This handle
|
||||
should be used for any future reference to the newly created mutex.
|
||||
If no optional <span class="opt">?-recursive?</span> argument was specified, the command
|
||||
creates the exclusive mutex. With the <span class="opt">?-recursive?</span> argument,
|
||||
the command creates a recursive mutex.</p></dd>
|
||||
<dt><a name="22"><b class="cmd">thread::mutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Destroys the <i class="arg">mutex</i>. Mutex should be in unlocked state before
|
||||
the destroy attempt. If the mutex is locked, the command will throw
|
||||
Tcl error.</p></dd>
|
||||
<dt><a name="23"><b class="cmd">thread::mutex</b> <b class="method">lock</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Locks the <i class="arg">mutex</i>. Locking the exclusive mutex may throw Tcl
|
||||
error if on attempt to lock the same mutex twice from the same
|
||||
thread. If your program logic forces you to lock the same mutex
|
||||
twice or more from the same thread (this may happen in recursive
|
||||
procedure invocations) you should consider using the recursive mutexes.</p></dd>
|
||||
<dt><a name="24"><b class="cmd">thread::mutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Unlocks the <i class="arg">mutex</i> so some other thread may lock it again.
|
||||
Attempt to unlock the already unlocked mutex will throw Tcl error.</p></dd>
|
||||
</dl></dd>
|
||||
<dt><a name="25"><b class="cmd">thread::rwmutex</b></a></dt>
|
||||
<dd><p>This command creates many-readers/single-writer mutexes. Reader/writer
|
||||
mutexes allow you to serialize access to a shared resource more optimally.
|
||||
In situations where a shared resource gets mostly read and seldom modified,
|
||||
you might gain some performace by using reader/writer mutexes instead of
|
||||
exclusive or recursive mutexes.</p>
|
||||
<p>For reading the resource, thread should obtain a read lock on the resource.
|
||||
Read lock is non-exclusive, meaning that more than one thread can
|
||||
obtain a read lock to the same resource, without waiting on other readers.
|
||||
For changing the resource, however, a thread must obtain a exclusive
|
||||
write lock. This lock effectively blocks all threads from gaining the
|
||||
read-lock while the resource is been modified by the writer thread.
|
||||
Only after the write lock has been released, the resource may be read-locked
|
||||
again.</p>
|
||||
<p>The <b class="cmd">thread::rwmutex</b> command supports following subcommands and options:</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="26"><b class="cmd">thread::rwmutex</b> <b class="method">create</b></a></dt>
|
||||
<dd><p>Creates the reader/writer mutex and returns it's opaque handle.
|
||||
This handle should be used for any future reference to the newly
|
||||
created mutex.</p></dd>
|
||||
<dt><a name="27"><b class="cmd">thread::rwmutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Destroys the reader/writer <i class="arg">mutex</i>. If the mutex is already locked,
|
||||
attempt to destroy it will throw Tcl error.</p></dd>
|
||||
<dt><a name="28"><b class="cmd">thread::rwmutex</b> <b class="method">rlock</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Locks the <i class="arg">mutex</i> for reading. More than one thread may read-lock
|
||||
the same <i class="arg">mutex</i> at the same time.</p></dd>
|
||||
<dt><a name="29"><b class="cmd">thread::rwmutex</b> <b class="method">wlock</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Locks the <i class="arg">mutex</i> for writing. Only one thread may write-lock
|
||||
the same <i class="arg">mutex</i> at the same time. Attempt to write-lock same
|
||||
<i class="arg">mutex</i> twice from the same thread will throw Tcl error.</p></dd>
|
||||
<dt><a name="30"><b class="cmd">thread::rwmutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></dt>
|
||||
<dd><p>Unlocks the <i class="arg">mutex</i> so some other thread may lock it again.
|
||||
Attempt to unlock already unlocked <i class="arg">mutex</i> will throw Tcl error.</p></dd>
|
||||
</dl></dd>
|
||||
<dt><a name="31"><b class="cmd">thread::cond</b></a></dt>
|
||||
<dd><p>This command provides script-level access to condition variables.
|
||||
A condition variable creates a safe environment for the program
|
||||
to test some condition, sleep on it when false and be awakened
|
||||
when it might have become true. A condition variable is always
|
||||
used in the conjuction with an exclusive mutex. If you attempt
|
||||
to use other type of mutex in conjuction with the condition
|
||||
variable, a Tcl error will be thrown.</p>
|
||||
<p>The command supports following subcommands and options:</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="32"><b class="cmd">thread::cond</b> <b class="method">create</b></a></dt>
|
||||
<dd><p>Creates the condition variable and returns it's opaque handle.
|
||||
This handle should be used for any future reference to newly
|
||||
created condition variable.</p></dd>
|
||||
<dt><a name="33"><b class="cmd">thread::cond</b> <b class="method">destroy</b> <i class="arg">cond</i></a></dt>
|
||||
<dd><p>Destroys condition variable <i class="arg">cond</i>. Extreme care has to be taken
|
||||
that nobody is using (i.e. waiting on) the condition variable,
|
||||
otherwise unexpected errors may happen.</p></dd>
|
||||
<dt><a name="34"><b class="cmd">thread::cond</b> <b class="method">notify</b> <i class="arg">cond</i></a></dt>
|
||||
<dd><p>Wakes up all threads waiting on the condition variable <i class="arg">cond</i>.</p></dd>
|
||||
<dt><a name="35"><b class="cmd">thread::cond</b> <b class="method">wait</b> <i class="arg">cond</i> <i class="arg">mutex</i> <span class="opt">?ms?</span></a></dt>
|
||||
<dd><p>This command is used to suspend program execution until the condition
|
||||
variable <i class="arg">cond</i> has been signalled or the optional timer has expired.
|
||||
The exclusive <i class="arg">mutex</i> must be locked by the calling thread on entrance
|
||||
to this command. If the mutex is not locked, Tcl error is thrown.
|
||||
While waiting on the <i class="arg">cond</i>, the command releases <i class="arg">mutex</i>.
|
||||
Before returning to the calling thread, the command re-acquires the
|
||||
<i class="arg">mutex</i> again. Unlocking the <i class="arg">mutex</i> and waiting on the
|
||||
condition variable <i class="arg">cond</i> is done atomically.</p>
|
||||
<p>The <b class="option">ms</b> command option, if given, must be an integer specifying
|
||||
time interval in milliseconds the command waits to be signalled.
|
||||
Otherwise the command waits on condition notify forever.</p>
|
||||
<p>In multithreading programs, there are many situations where a thread has
|
||||
to wait for some event to happen until it is allowed to proceed.
|
||||
This is usually accomplished by repeatedly testing a condition under the
|
||||
mutex protection and waiting on the condition variable until the condition
|
||||
evaluates to true:</p>
|
||||
<pre class="doctools_example">
|
||||
set mutex [thread::mutex create]
|
||||
set cond [thread::cond create]
|
||||
thread::mutex lock $mutex
|
||||
while {<some_condition_is_true>} {
|
||||
thread::cond wait $cond $mutex
|
||||
}
|
||||
# Do some work under mutex protection
|
||||
thread::mutex unlock $mutex
|
||||
</pre>
|
||||
<p>Repeated testing of the condition is needed since the condition variable
|
||||
may get signalled without the condition being actually changed (spurious
|
||||
thread wake-ups, for example).</p></dd>
|
||||
</dl></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section3" class="doctools_section"><h2><a name="section3">DISCUSSION</a></h2>
|
||||
<p>The fundamental threading model in Tcl is that there can be one or
|
||||
more Tcl interpreters per thread, but each Tcl interpreter should
|
||||
only be used by a single thread which created it.
|
||||
A "shared memory" abstraction is awkward to provide in Tcl because
|
||||
Tcl makes assumptions about variable and data ownership. Therefore
|
||||
this extension supports a simple form of threading where the main
|
||||
thread can manage several background, or "worker" threads.
|
||||
For example, an event-driven server can pass requests to worker
|
||||
threads, and then await responses from worker threads or new client
|
||||
requests. Everything goes through the common Tcl event loop, so
|
||||
message passing between threads works naturally with event-driven I/O,
|
||||
<b class="cmd">vwait</b> on variables, and so forth. For the transfer of bulk
|
||||
information it is possible to move channels between the threads.</p>
|
||||
<p>For advanced multithreading scripts, script-level access to two
|
||||
basic synchronization primitives, mutex and condition variables,
|
||||
is also supported.</p>
|
||||
</div>
|
||||
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
|
||||
<p><a href="http://www.tcl.tk/doc/howto/thread_model.html">http://www.tcl.tk/doc/howto/thread_model.html</a>, tpool, tsv, ttrace</p>
|
||||
</div>
|
||||
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
|
||||
<p>events, message passing, mutex, synchronization, thread</p>
|
||||
</div>
|
||||
</div></body></html>
|
||||
|
||||
316
pkgs/thread2.8.7/doc/html/tpool.html
Normal file
316
pkgs/thread2.8.7/doc/html/tpool.html
Normal file
@@ -0,0 +1,316 @@
|
||||
|
||||
<html><head>
|
||||
<title>tpool - Tcl Threading</title>
|
||||
<style type="text/css"><!--
|
||||
HTML {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
BODY {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
DIV.doctools {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
DIV.doctools H1,DIV.doctools H2 {
|
||||
margin-left: -5%;
|
||||
}
|
||||
H1, H2, H3, H4 {
|
||||
margin-top: 1em;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
color: #005A9C;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
}
|
||||
H1.doctools_title {
|
||||
text-align: center;
|
||||
}
|
||||
UL,OL {
|
||||
margin-right: 0em;
|
||||
margin-top: 3pt;
|
||||
margin-bottom: 3pt;
|
||||
}
|
||||
UL LI {
|
||||
list-style: disc;
|
||||
}
|
||||
OL LI {
|
||||
list-style: decimal;
|
||||
}
|
||||
DT {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
|
||||
font: normal 12pt/14pt sans-serif;
|
||||
list-style: none;
|
||||
}
|
||||
LI.doctools_section, LI.doctools_subsection {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
PRE {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
margin: 0%;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0.5ex;
|
||||
padding-left: 1ex;
|
||||
padding-right: 1ex;
|
||||
width: 100%;
|
||||
}
|
||||
PRE.doctools_example {
|
||||
color: black;
|
||||
background: #f5dcb3;
|
||||
border: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements LI, UL.doctools_syntax LI {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
DIV.doctools_synopsis {
|
||||
color: black;
|
||||
background: #80ffff;
|
||||
border: 1px solid black;
|
||||
font-family: serif;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
UL.doctools_syntax {
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements {
|
||||
margin-bottom: 1em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
--></style>
|
||||
</head>
|
||||
<! -- Generated from file '' by tcllib/doctools with format 'html'
|
||||
-->
|
||||
<! -- tpool.n
|
||||
-->
|
||||
<body><div class="doctools">
|
||||
<h1 class="doctools_title">tpool(n) 2.8 "Tcl Threading"</h1>
|
||||
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
|
||||
<p>tpool - Part of the Tcl threading extension implementing pools of worker threads.</p>
|
||||
</div>
|
||||
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
|
||||
<ul class="doctools_toc">
|
||||
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
|
||||
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
|
||||
<li class="doctools_section"><a href="#section1">Description</a></li>
|
||||
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section3">DISCUSSION</a></li>
|
||||
<li class="doctools_section"><a href="#see-also">See Also</a></li>
|
||||
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
|
||||
<div class="doctools_synopsis">
|
||||
<ul class="doctools_requirements">
|
||||
<li>package require <b class="pkgname">Tcl 8.4</b></li>
|
||||
<li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li>
|
||||
</ul>
|
||||
<ul class="doctools_syntax">
|
||||
<li><a href="#1"><b class="cmd">tpool::create</b> <span class="opt">?options?</span></a></li>
|
||||
<li><a href="#2"><b class="cmd">tpool::names</b></a></li>
|
||||
<li><a href="#3"><b class="cmd">tpool::post</b> <span class="opt">?-detached?</span> <span class="opt">?-nowait?</span> <i class="arg">tpool</i> <i class="arg">script</i></a></li>
|
||||
<li><a href="#4"><b class="cmd">tpool::wait</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></li>
|
||||
<li><a href="#5"><b class="cmd">tpool::cancel</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></li>
|
||||
<li><a href="#6"><b class="cmd">tpool::get</b> <i class="arg">tpool</i> <i class="arg">job</i></a></li>
|
||||
<li><a href="#7"><b class="cmd">tpool::preserve</b> <i class="arg">tpool</i></a></li>
|
||||
<li><a href="#8"><b class="cmd">tpool::release</b> <i class="arg">tpool</i></a></li>
|
||||
<li><a href="#9"><b class="cmd">tpool::suspend</b> <i class="arg">tpool</i></a></li>
|
||||
<li><a href="#10"><b class="cmd">tpool::resume</b> <i class="arg">tpool</i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
|
||||
<p>This package creates and manages pools of worker threads. It allows you
|
||||
to post jobs to worker threads and wait for their completion. The
|
||||
threadpool implementation is Tcl event-loop aware. That means that any
|
||||
time a caller is forced to wait for an event (job being completed or
|
||||
a worker thread becoming idle or initialized), the implementation will
|
||||
enter the event loop and allow for servicing of other pending file or
|
||||
timer (or any other supported) events.</p>
|
||||
</div>
|
||||
<div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="1"><b class="cmd">tpool::create</b> <span class="opt">?options?</span></a></dt>
|
||||
<dd><p>This command creates new threadpool. It accepts several options as
|
||||
key-value pairs. Options are used to tune some threadpool parameters.
|
||||
The command returns the ID of the newly created threadpool.</p>
|
||||
<p>Following options are supported:</p>
|
||||
<dl class="doctools_options">
|
||||
<dt><b class="option">-minworkers</b> <i class="arg">number</i></dt>
|
||||
<dd><p>Minimum number of worker threads needed for this threadpool instance.
|
||||
During threadpool creation, the implementation will create somany
|
||||
worker threads upfront and will keep at least number of them alive
|
||||
during the lifetime of the threadpool instance.
|
||||
Default value of this parameter is 0 (zero). which means that a newly
|
||||
threadpool will have no worker threads initialy. All worker threads
|
||||
will be started on demand by callers running <b class="cmd">tpool::post</b> command
|
||||
and posting jobs to the job queue.</p></dd>
|
||||
<dt><b class="option">-maxworkers</b> <i class="arg">number</i></dt>
|
||||
<dd><p>Maximum number of worker threads allowed for this threadpool instance.
|
||||
If a new job is pending and there are no idle worker threads available,
|
||||
the implementation will try to create new worker thread. If the number
|
||||
of available worker threads is lower than the given number,
|
||||
new worker thread will start. The caller will automatically enter the
|
||||
event loop and wait until the worker thread has initialized. If. however,
|
||||
the number of available worker threads is equal to the given number,
|
||||
the caller will enter the event loop and wait for the first worker thread
|
||||
to get idle, thus ready to run the job.
|
||||
Default value of this parameter is 4 (four), which means that the
|
||||
threadpool instance will allow maximum of 4 worker threads running jobs
|
||||
or being idle waiting for new jobs to get posted to the job queue.</p></dd>
|
||||
<dt><b class="option">-idletime</b> <i class="arg">seconds</i></dt>
|
||||
<dd><p>Time in seconds an idle worker thread waits for the job to get posted
|
||||
to the job queue. If no job arrives during this interval and the time
|
||||
expires, the worker thread will check the number of currently available
|
||||
worker threads and if the number is higher than the number set by the
|
||||
<b class="option">minthreads</b> option, it will exit.
|
||||
If an <b class="option">exitscript</b> has been defined, the exiting worker thread
|
||||
will first run the script and then exit. Errors from the exit script,
|
||||
if any, are ignored.</p>
|
||||
<p>The idle worker thread is not servicing the event loop. If you, however,
|
||||
put the worker thread into the event loop, by evaluating the
|
||||
<b class="cmd">vwait</b> or other related Tcl commands, the worker thread
|
||||
will not be in the idle state, hence the idle timer will not be
|
||||
taken into account.
|
||||
Default value for this option is unspecified.</p></dd>
|
||||
<dt><b class="option">-initcmd</b> <i class="arg">script</i></dt>
|
||||
<dd><p>Sets a Tcl script used to initialize new worker thread. This is usually
|
||||
used to load packages and commands in the worker, set default variables,
|
||||
create namespaces, and such. If the passed script runs into a Tcl error,
|
||||
the worker will not be created and the initiating command (either the
|
||||
<b class="cmd">tpool::create</b> or <b class="cmd">tpool::post</b>) will throw error.
|
||||
Default value for this option is unspecified, hence, the Tcl interpreter of
|
||||
the worker thread will contain just the initial set of Tcl commands.</p></dd>
|
||||
<dt><b class="option">-exitcmd</b> <i class="arg">script</i></dt>
|
||||
<dd><p>Sets a Tcl script run when the idle worker thread exits. This is normaly
|
||||
used to cleanup the state of the worker thread, release reserved resources,
|
||||
cleanup memory and such.
|
||||
Default value for this option is unspecified, thus no Tcl script will run
|
||||
on the worker thread exit.</p></dd>
|
||||
</dl></dd>
|
||||
<dt><a name="2"><b class="cmd">tpool::names</b></a></dt>
|
||||
<dd><p>This command returns a list of IDs of threadpools created with the
|
||||
<b class="cmd">tpool::create</b> command. If no threadpools were found, the
|
||||
command will return empty list.</p></dd>
|
||||
<dt><a name="3"><b class="cmd">tpool::post</b> <span class="opt">?-detached?</span> <span class="opt">?-nowait?</span> <i class="arg">tpool</i> <i class="arg">script</i></a></dt>
|
||||
<dd><p>This command sends a <i class="arg">script</i> to the target <i class="arg">tpool</i> threadpool
|
||||
for execution. The script will be executed in the first available idle
|
||||
worker thread. If there are no idle worker threads available, the command
|
||||
will create new one, enter the event loop and service events until the
|
||||
newly created thread is initialized. If the current number of worker
|
||||
threads is equal to the maximum number of worker threads, as defined
|
||||
during the threadpool creation, the command will enter the event loop and
|
||||
service events while waiting for one of the worker threads to become idle.
|
||||
If the optional <span class="opt">?-nowait?</span> argument is given, the command will not wait
|
||||
for one idle worker. It will just place the job in the pool's job queue
|
||||
and return immediately.</p>
|
||||
<p>The command returns the ID of the posted job. This ID is used for subsequent
|
||||
<b class="cmd">tpool::wait</b>, <b class="cmd">tpool::get</b> and <b class="cmd">tpool::cancel</b> commands to wait
|
||||
for and retrieve result of the posted script, or cancel the posted job
|
||||
respectively. If the optional <span class="opt">?-detached?</span> argument is specified, the
|
||||
command will post a detached job. A detached job can not be cancelled or
|
||||
waited upon and is not identified by the job ID.</p>
|
||||
<p>If the threadpool <i class="arg">tpool</i> is not found in the list of active
|
||||
thread pools, the command will throw error. The error will also be triggered
|
||||
if the newly created worker thread fails to initialize.</p></dd>
|
||||
<dt><a name="4"><b class="cmd">tpool::wait</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></dt>
|
||||
<dd><p>This command waits for one or many jobs, whose job IDs are given in the
|
||||
<i class="arg">joblist</i> to get processed by the worker thread(s). If none of the
|
||||
specified jobs are ready, the command will enter the event loop, service
|
||||
events and wait for the first job to get ready.</p>
|
||||
<p>The command returns the list of completed job IDs. If the optional variable
|
||||
<span class="opt">?varname?</span> is given, it will be set to the list of jobs in the
|
||||
<i class="arg">joblist</i> which are still pending. If the threadpool <i class="arg">tpool</i>
|
||||
is not found in the list of active thread pools, the command will throw error.</p></dd>
|
||||
<dt><a name="5"><b class="cmd">tpool::cancel</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></dt>
|
||||
<dd><p>This command cancels the previously posted jobs given by the <i class="arg">joblist</i>
|
||||
to the pool <i class="arg">tpool</i>. Job cancellation succeeds only for job still
|
||||
waiting to be processed. If the job is already being executed by one of
|
||||
the worker threads, the job will not be cancelled.
|
||||
The command returns the list of cancelled job IDs. If the optional variable
|
||||
<span class="opt">?varname?</span> is given, it will be set to the list of jobs in the
|
||||
<i class="arg">joblist</i> which were not cancelled. If the threadpool <i class="arg">tpool</i>
|
||||
is not found in the list of active thread pools, the command will throw error.</p></dd>
|
||||
<dt><a name="6"><b class="cmd">tpool::get</b> <i class="arg">tpool</i> <i class="arg">job</i></a></dt>
|
||||
<dd><p>This command retrieves the result of the previously posted <i class="arg">job</i>.
|
||||
Only results of jobs waited upon with the <b class="cmd">tpool::wait</b> command
|
||||
can be retrieved. If the execution of the script resulted in error,
|
||||
the command will throw the error and update the <b class="variable">errorInfo</b> and
|
||||
<b class="variable">errorCode</b> variables correspondingly. If the pool <i class="arg">tpool</i>
|
||||
is not found in the list of threadpools, the command will throw error.
|
||||
If the job <i class="arg">job</i> is not ready for retrieval, because it is currently
|
||||
being executed by the worker thread, the command will throw error.</p></dd>
|
||||
<dt><a name="7"><b class="cmd">tpool::preserve</b> <i class="arg">tpool</i></a></dt>
|
||||
<dd><p>Each call to this command increments the reference counter of the
|
||||
threadpool <i class="arg">tpool</i> by one (1). Command returns the value of the
|
||||
reference counter after the increment.
|
||||
By incrementing the reference counter, the caller signalizes that
|
||||
he/she wishes to use the resource for a longer period of time.</p></dd>
|
||||
<dt><a name="8"><b class="cmd">tpool::release</b> <i class="arg">tpool</i></a></dt>
|
||||
<dd><p>Each call to this command decrements the reference counter of the
|
||||
threadpool <i class="arg">tpool</i> by one (1).Command returns the value of the
|
||||
reference counter after the decrement.
|
||||
When the reference counter reaches zero (0), the threadpool <i class="arg">tpool</i>
|
||||
is marked for termination. You should not reference the threadpool
|
||||
after the <b class="cmd">tpool::release</b> command returns zero. The <i class="arg">tpool</i>
|
||||
handle goes out of scope and should not be used any more. Any following
|
||||
reference to the same threadpool handle will result in Tcl error.</p></dd>
|
||||
<dt><a name="9"><b class="cmd">tpool::suspend</b> <i class="arg">tpool</i></a></dt>
|
||||
<dd><p>Suspends processing work on this queue. All pool workers are paused
|
||||
but additional work can be added to the pool. Note that adding the
|
||||
additional work will not increase the number of workers dynamically
|
||||
as the pool processing is suspended. Number of workers is maintained
|
||||
to the count that was found prior suspending worker activity.
|
||||
If you need to assure certain number of worker threads, use the
|
||||
<b class="option">minworkers</b> option of the <b class="cmd">tpool::create</b> command.</p></dd>
|
||||
<dt><a name="10"><b class="cmd">tpool::resume</b> <i class="arg">tpool</i></a></dt>
|
||||
<dd><p>Resume processing work on this queue. All paused (suspended)
|
||||
workers are free to get work from the pool. Note that resuming pool
|
||||
operation will just let already created workers to proceed.
|
||||
It will not create additional worker threads to handle the work
|
||||
posted to the pool's work queue.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section3" class="doctools_section"><h2><a name="section3">DISCUSSION</a></h2>
|
||||
<p>Threadpool is one of the most common threading paradigm when it comes
|
||||
to server applications handling a large number of relatively small tasks.
|
||||
A very simplistic model for building a server application would be to
|
||||
create a new thread each time a request arrives and service the request
|
||||
in the new thread. One of the disadvantages of this approach is that
|
||||
the overhead of creating a new thread for each request is significant;
|
||||
a server that created a new thread for each request would spend more time
|
||||
and consume more system resources in creating and destroying threads than
|
||||
in processing actual user requests. In addition to the overhead of
|
||||
creating and destroying threads, active threads consume system resources.
|
||||
Creating too many threads can cause the system to run out of memory or
|
||||
trash due to excessive memory consumption.</p>
|
||||
<p>A thread pool offers a solution to both the problem of thread life-cycle
|
||||
overhead and the problem of resource trashing. By reusing threads for
|
||||
multiple tasks, the thread-creation overhead is spread over many tasks.
|
||||
As a bonus, because the thread already exists when a request arrives,
|
||||
the delay introduced by thread creation is eliminated. Thus, the request
|
||||
can be serviced immediately. Furthermore, by properly tuning the number
|
||||
of threads in the thread pool, resource thrashing may also be eliminated
|
||||
by forcing any request to wait until a thread is available to process it.</p>
|
||||
</div>
|
||||
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
|
||||
<p>thread, tsv, ttrace</p>
|
||||
</div>
|
||||
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
|
||||
<p>thread, threadpool</p>
|
||||
</div>
|
||||
</div></body></html>
|
||||
|
||||
409
pkgs/thread2.8.7/doc/html/tsv.html
Normal file
409
pkgs/thread2.8.7/doc/html/tsv.html
Normal file
@@ -0,0 +1,409 @@
|
||||
|
||||
<html><head>
|
||||
<title>tsv - Tcl Threading</title>
|
||||
<style type="text/css"><!--
|
||||
HTML {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
BODY {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
DIV.doctools {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
DIV.doctools H1,DIV.doctools H2 {
|
||||
margin-left: -5%;
|
||||
}
|
||||
H1, H2, H3, H4 {
|
||||
margin-top: 1em;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
color: #005A9C;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
}
|
||||
H1.doctools_title {
|
||||
text-align: center;
|
||||
}
|
||||
UL,OL {
|
||||
margin-right: 0em;
|
||||
margin-top: 3pt;
|
||||
margin-bottom: 3pt;
|
||||
}
|
||||
UL LI {
|
||||
list-style: disc;
|
||||
}
|
||||
OL LI {
|
||||
list-style: decimal;
|
||||
}
|
||||
DT {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
|
||||
font: normal 12pt/14pt sans-serif;
|
||||
list-style: none;
|
||||
}
|
||||
LI.doctools_section, LI.doctools_subsection {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
PRE {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
margin: 0%;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0.5ex;
|
||||
padding-left: 1ex;
|
||||
padding-right: 1ex;
|
||||
width: 100%;
|
||||
}
|
||||
PRE.doctools_example {
|
||||
color: black;
|
||||
background: #f5dcb3;
|
||||
border: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements LI, UL.doctools_syntax LI {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
DIV.doctools_synopsis {
|
||||
color: black;
|
||||
background: #80ffff;
|
||||
border: 1px solid black;
|
||||
font-family: serif;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
UL.doctools_syntax {
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements {
|
||||
margin-bottom: 1em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
--></style>
|
||||
</head>
|
||||
<! -- Generated from file '' by tcllib/doctools with format 'html'
|
||||
-->
|
||||
<! -- tsv.n
|
||||
-->
|
||||
<body><div class="doctools">
|
||||
<h1 class="doctools_title">tsv(n) 2.8 "Tcl Threading"</h1>
|
||||
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
|
||||
<p>tsv - Part of the Tcl threading extension allowing script level manipulation of data shared between threads.</p>
|
||||
</div>
|
||||
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
|
||||
<ul class="doctools_toc">
|
||||
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
|
||||
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
|
||||
<li class="doctools_section"><a href="#section1">Description</a></li>
|
||||
<li class="doctools_section"><a href="#section2">ELEMENT COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section3">LIST COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section4">ARRAY COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section5">KEYED LIST COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section6">DISCUSSION</a></li>
|
||||
<li class="doctools_section"><a href="#section7">CREDITS</a></li>
|
||||
<li class="doctools_section"><a href="#see-also">See Also</a></li>
|
||||
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
|
||||
<div class="doctools_synopsis">
|
||||
<ul class="doctools_requirements">
|
||||
<li>package require <b class="pkgname">Tcl 8.4</b></li>
|
||||
<li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li>
|
||||
</ul>
|
||||
<ul class="doctools_syntax">
|
||||
<li><a href="#1"><b class="cmd">tsv::names</b> <span class="opt">?pattern?</span></a></li>
|
||||
<li><a href="#2"><b class="cmd">tsv::object</b> <i class="arg">varname</i> <i class="arg">element</i></a></li>
|
||||
<li><a href="#3"><b class="cmd">tsv::set</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?value?</span></a></li>
|
||||
<li><a href="#4"><b class="cmd">tsv::get</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?namedvar?</span></a></li>
|
||||
<li><a href="#5"><b class="cmd">tsv::unset</b> <i class="arg">varname</i> <span class="opt">?element?</span></a></li>
|
||||
<li><a href="#6"><b class="cmd">tsv::exists</b> <i class="arg">varname</i> <i class="arg">element</i></a></li>
|
||||
<li><a href="#7"><b class="cmd">tsv::pop</b> <i class="arg">varname</i> <i class="arg">element</i></a></li>
|
||||
<li><a href="#8"><b class="cmd">tsv::move</b> <i class="arg">varname</i> <i class="arg">oldname</i> <i class="arg">newname</i></a></li>
|
||||
<li><a href="#9"><b class="cmd">tsv::incr</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?count?</span></a></li>
|
||||
<li><a href="#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></li>
|
||||
<li><a href="#11"><b class="cmd">tsv::lock</b> <i class="arg">varname</i> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li>
|
||||
<li><a href="#12"><b class="cmd">tsv::handlers</b></a></li>
|
||||
<li><a href="#13"><b class="cmd">tsv::lappend</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></li>
|
||||
<li><a href="#14"><b class="cmd">tsv::linsert</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></li>
|
||||
<li><a href="#15"><b class="cmd">tsv::lreplace</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">first</i> <i class="arg">last</i> <span class="opt">?value ...?</span></a></li>
|
||||
<li><a href="#16"><b class="cmd">tsv::llength</b> <i class="arg">varname</i> <i class="arg">element</i></a></li>
|
||||
<li><a href="#17"><b class="cmd">tsv::lindex</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li>
|
||||
<li><a href="#18"><b class="cmd">tsv::lrange</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">from</i> <i class="arg">to</i></a></li>
|
||||
<li><a href="#19"><b class="cmd">tsv::lsearch</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?options?</span> <i class="arg">pattern</i></a></li>
|
||||
<li><a href="#20"><b class="cmd">tsv::lset</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <span class="opt">?index ...?</span> <i class="arg">value</i></a></li>
|
||||
<li><a href="#21"><b class="cmd">tsv::lpop</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li>
|
||||
<li><a href="#22"><b class="cmd">tsv::lpush</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li>
|
||||
<li><a href="#23"><b class="cmd">tsv::array set</b> <i class="arg">varname</i> <i class="arg">list</i></a></li>
|
||||
<li><a href="#24"><b class="cmd">tsv::array get</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></li>
|
||||
<li><a href="#25"><b class="cmd">tsv::array names</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></li>
|
||||
<li><a href="#26"><b class="cmd">tsv::array size</b> <i class="arg">varname</i></a></li>
|
||||
<li><a href="#27"><b class="cmd">tsv::array reset</b> <i class="arg">varname</i> <i class="arg">list</i></a></li>
|
||||
<li><a href="#28"><b class="cmd">tsv::array bind</b> <i class="arg">varname</i> <i class="arg">handle</i></a></li>
|
||||
<li><a href="#29"><b class="cmd">tsv::array unbind</b> <i class="arg">varname</i></a></li>
|
||||
<li><a href="#30"><b class="cmd">tsv::array isbound</b> <i class="arg">varname</i></a></li>
|
||||
<li><a href="#31"><b class="cmd">tsv::keyldel</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i></a></li>
|
||||
<li><a href="#32"><b class="cmd">tsv::keylget</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <span class="opt">?retvar?</span></a></li>
|
||||
<li><a href="#33"><b class="cmd">tsv::keylkeys</b> <i class="arg">varname</i> <i class="arg">keylist</i> <span class="opt">?key?</span></a></li>
|
||||
<li><a href="#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></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
|
||||
<p>This section describes commands implementing thread shared variables.
|
||||
A thread shared variable is very similar to a Tcl array but in
|
||||
contrast to a Tcl array it is created in shared memory and can
|
||||
be accessed from many threads at the same time. Important feature of
|
||||
thread shared variable is that each access to the variable is internaly
|
||||
protected by a mutex so script programmer does not have to take care
|
||||
about locking the variable himself.</p>
|
||||
<p>Thread shared variables are not bound to any thread explicitly. That
|
||||
means that when a thread which created any of thread shared variables
|
||||
exits, the variable and associated memory is not unset/reclaimed.
|
||||
User has to explicitly unset the variable to reclaim the memory
|
||||
consumed by the variable.</p>
|
||||
</div>
|
||||
<div id="section2" class="doctools_section"><h2><a name="section2">ELEMENT COMMANDS</a></h2>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="1"><b class="cmd">tsv::names</b> <span class="opt">?pattern?</span></a></dt>
|
||||
<dd><p>Returns names of shared variables matching optional <span class="opt">?pattern?</span>
|
||||
or all known variables if pattern is ommited.</p></dd>
|
||||
<dt><a name="2"><b class="cmd">tsv::object</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
|
||||
<dd><p>Creates object accessor command for the <i class="arg">element</i> in the
|
||||
shared variable <i class="arg">varname</i>. Using this command, one can apply most
|
||||
of the other shared variable commands as method functions of
|
||||
the element object command. The object command is automatically
|
||||
deleted when the element which this command is pointing to is unset.</p>
|
||||
<pre class="doctools_example">
|
||||
% tsv::set foo bar "A shared string"
|
||||
% set string [tsv::object foo bar]
|
||||
% $string append " appended"
|
||||
=> A shared string appended
|
||||
</pre>
|
||||
</dd>
|
||||
<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>
|
||||
<dd><p>Sets the value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i>
|
||||
to <i class="arg">value</i> and returns the value to caller. The <i class="arg">value</i>
|
||||
may be ommited, in which case the command will return the current
|
||||
value of the element. If the element cannot be found, error is triggered.</p></dd>
|
||||
<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>
|
||||
<dd><p>Retrieves the value of the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>.
|
||||
If the optional argument <i class="arg">namedvar</i> is given, the value is
|
||||
stored in the named variable. Return value of the command depends
|
||||
of the existence of the optional argument <i class="arg">namedvar</i>.
|
||||
If the argument is ommited and the requested element cannot be found
|
||||
in the shared array, the command triggers error. If, however, the
|
||||
optional argument is given on the command line, the command returns
|
||||
true (1) if the element is found or false (0) if the element is not found.</p></dd>
|
||||
<dt><a name="5"><b class="cmd">tsv::unset</b> <i class="arg">varname</i> <span class="opt">?element?</span></a></dt>
|
||||
<dd><p>Unsets the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>.
|
||||
If the optional element is not given, it deletes the variable.</p></dd>
|
||||
<dt><a name="6"><b class="cmd">tsv::exists</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
|
||||
<dd><p>Checks wether the <i class="arg">element</i> exists in the shared variable <i class="arg">varname</i>
|
||||
and returns true (1) if it does or false (0) if it doesn't.</p></dd>
|
||||
<dt><a name="7"><b class="cmd">tsv::pop</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
|
||||
<dd><p>Returns value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i>
|
||||
and unsets the element, all in one atomic operation.</p></dd>
|
||||
<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>
|
||||
<dd><p>Renames the element <i class="arg">oldname</i> to the <i class="arg">newname</i> in the
|
||||
shared variable <i class="arg">varname</i>. This effectively performs an get/unset/set
|
||||
sequence of operations but all in one atomic step.</p></dd>
|
||||
<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>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">incr</b> command but increments the value
|
||||
of the <i class="arg">element</i> in shared variaboe <i class="arg">varname</i> instead of
|
||||
the Tcl variable.</p></dd>
|
||||
<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>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">append</b> command but appends one or more
|
||||
values to the <i class="arg">element</i> in shared variable <i class="arg">varname</i> instead of the
|
||||
Tcl variable.</p></dd>
|
||||
<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>
|
||||
<dd><p>This command concatenates passed arguments and evaluates the
|
||||
resulting script under the internal mutex protection. During the
|
||||
script evaluation, the entire shared variable is locked. For shared
|
||||
variable commands within the script, internal locking is disabled
|
||||
so no deadlock can occur. It is also allowed to unset the shared
|
||||
variable from within the script. The shared variable is automatically
|
||||
created if it did not exists at the time of the first lock operation.</p>
|
||||
<pre class="doctools_example">
|
||||
% tsv::lock foo {
|
||||
tsv::lappend foo bar 1
|
||||
tsv::lappend foo bar 2
|
||||
puts stderr [tsv::set foo bar]
|
||||
tsv::unset foo
|
||||
}
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><a name="12"><b class="cmd">tsv::handlers</b></a></dt>
|
||||
<dd><p>Returns the names of all persistent storage handlers enabled at compile time.
|
||||
See <span class="sectref"><a href="#section4">ARRAY COMMANDS</a></span> for details.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section3" class="doctools_section"><h2><a name="section3">LIST COMMANDS</a></h2>
|
||||
<p>Those command are similar to the equivalently named Tcl command. The difference
|
||||
is that they operate on elements of shared arrays.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="13"><b class="cmd">tsv::lappend</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lappend</b> command but appends one
|
||||
or more values to the <i class="arg">element</i> in shared variable <i class="arg">varname</i>
|
||||
instead of the Tcl variable.</p></dd>
|
||||
<dt><a name="14"><b class="cmd">tsv::linsert</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">linsert</b> command but inserts one
|
||||
or more values at the <i class="arg">index</i> list position in the
|
||||
<i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd>
|
||||
<dt><a name="15"><b class="cmd">tsv::lreplace</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">first</i> <i class="arg">last</i> <span class="opt">?value ...?</span></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lreplace</b> command but replaces one
|
||||
or more values between the <i class="arg">first</i> and <i class="arg">last</i> position
|
||||
in the <i class="arg">element</i> of the shared variable <i class="arg">varname</i> instead of
|
||||
the Tcl variable.</p></dd>
|
||||
<dt><a name="16"><b class="cmd">tsv::llength</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">llength</b> command but returns length
|
||||
of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl
|
||||
variable.</p></dd>
|
||||
<dt><a name="17"><b class="cmd">tsv::lindex</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lindex</b> command but returns the value
|
||||
at the <i class="arg">index</i> list position of the <i class="arg">element</i> from
|
||||
the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd>
|
||||
<dt><a name="18"><b class="cmd">tsv::lrange</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">from</i> <i class="arg">to</i></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lrange</b> command but returns values
|
||||
between <i class="arg">from</i> and <i class="arg">to</i> list positions from the
|
||||
<i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd>
|
||||
<dt><a name="19"><b class="cmd">tsv::lsearch</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?options?</span> <i class="arg">pattern</i></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lsearch</b> command but searches the <i class="arg">element</i>
|
||||
in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd>
|
||||
<dt><a name="20"><b class="cmd">tsv::lset</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <span class="opt">?index ...?</span> <i class="arg">value</i></a></dt>
|
||||
<dd><p>Similar to standard Tcl <b class="cmd">lset</b> command but sets the <i class="arg">element</i>
|
||||
in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd>
|
||||
<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>
|
||||
<dd><p>Similar to the standard Tcl <b class="cmd">lindex</b> command but in addition to
|
||||
returning, it also splices the value out of the <i class="arg">element</i>
|
||||
from the shared variable <i class="arg">varname</i> in one atomic operation.
|
||||
In contrast to the Tcl <b class="cmd">lindex</b> command, this command returns
|
||||
no value to the caller.</p></dd>
|
||||
<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>
|
||||
<dd><p>This command performes the opposite of the <b class="cmd">tsv::lpop</b> command.
|
||||
As its counterpart, it returns no value to the caller.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section4" class="doctools_section"><h2><a name="section4">ARRAY COMMANDS</a></h2>
|
||||
<p>This command supports most of the options of the standard Tcl
|
||||
<b class="cmd">array</b> command. In addition to those, it allows binding
|
||||
a shared variable to some persisten storage databases. Currently the persistent
|
||||
options supported are the famous GNU Gdbm and LMDB. These options have to be
|
||||
selected during the package compilation time.
|
||||
The implementation provides hooks for defining other persistency layers, if
|
||||
needed.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="23"><b class="cmd">tsv::array set</b> <i class="arg">varname</i> <i class="arg">list</i></a></dt>
|
||||
<dd><p>Does the same as standard Tcl <b class="cmd">array set</b>.</p></dd>
|
||||
<dt><a name="24"><b class="cmd">tsv::array get</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></dt>
|
||||
<dd><p>Does the same as standard Tcl <b class="cmd">array get</b>.</p></dd>
|
||||
<dt><a name="25"><b class="cmd">tsv::array names</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></dt>
|
||||
<dd><p>Does the same as standard Tcl <b class="cmd">array names</b>.</p></dd>
|
||||
<dt><a name="26"><b class="cmd">tsv::array size</b> <i class="arg">varname</i></a></dt>
|
||||
<dd><p>Does the same as standard Tcl <b class="cmd">array size</b>.</p></dd>
|
||||
<dt><a name="27"><b class="cmd">tsv::array reset</b> <i class="arg">varname</i> <i class="arg">list</i></a></dt>
|
||||
<dd><p>Does the same as standard Tcl <b class="cmd">array set</b> but it clears
|
||||
the <i class="arg">varname</i> and sets new values from the list atomically.</p></dd>
|
||||
<dt><a name="28"><b class="cmd">tsv::array bind</b> <i class="arg">varname</i> <i class="arg">handle</i></a></dt>
|
||||
<dd><p>Binds the <i class="arg">varname</i> to the persistent storage <i class="arg">handle</i>.
|
||||
The format of the <i class="arg">handle</i> is <handler>:<address>, where <handler> is
|
||||
"gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the
|
||||
database file.</p></dd>
|
||||
<dt><a name="29"><b class="cmd">tsv::array unbind</b> <i class="arg">varname</i></a></dt>
|
||||
<dd><p>Unbinds the shared <i class="arg">array</i> from its bound persistent storage.</p></dd>
|
||||
<dt><a name="30"><b class="cmd">tsv::array isbound</b> <i class="arg">varname</i></a></dt>
|
||||
<dd><p>Returns true (1) if the shared <i class="arg">varname</i> is bound to some
|
||||
persistent storage or zero (0) if not.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section5" class="doctools_section"><h2><a name="section5">KEYED LIST COMMANDS</a></h2>
|
||||
<p>Keyed list commands are borrowed from the TclX package. Keyed lists provide
|
||||
a structured data type built upon standard Tcl lists. This is a functionality
|
||||
similar to structs in the C programming language.</p>
|
||||
<p>A keyed list is a list in which each element contains a key and value
|
||||
pair. These element pairs are stored as lists themselves, where the key
|
||||
is the first element of the list, and the value is the second. The
|
||||
key-value pairs are referred to as fields. This is an example of a
|
||||
keyed list:</p>
|
||||
<pre class="doctools_example">
|
||||
{{NAME {Frank Zappa}} {JOB {musician and composer}}}
|
||||
</pre>
|
||||
<p>Fields may contain subfields; `.' is the separator character. Subfields
|
||||
are actually fields where the value is another keyed list. Thus the
|
||||
following list has the top level fields ID and NAME, and subfields
|
||||
NAME.FIRST and NAME.LAST:</p>
|
||||
<pre class="doctools_example">
|
||||
{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}
|
||||
</pre>
|
||||
<p>There is no limit to the recursive depth of subfields,
|
||||
allowing one to build complex data structures. Keyed lists are constructed
|
||||
and accessed via a number of commands. All keyed list management
|
||||
commands take the name of the variable containing the keyed list as an
|
||||
argument (i.e. passed by reference), rather than passing the list directly.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="31"><b class="cmd">tsv::keyldel</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i></a></dt>
|
||||
<dd><p>Delete the field specified by <i class="arg">key</i> from the keyed list <i class="arg">keylist</i>
|
||||
in the shared variable <i class="arg">varname</i>.
|
||||
This removes both the key and the value from the keyed list.</p></dd>
|
||||
<dt><a name="32"><b class="cmd">tsv::keylget</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <span class="opt">?retvar?</span></a></dt>
|
||||
<dd><p>Return the value associated with <i class="arg">key</i> from the keyed list <i class="arg">keylist</i>
|
||||
in the shared variable <i class="arg">varname</i>.
|
||||
If the optional <i class="arg">retvar</i> is not specified, then the value will be
|
||||
returned as the result of the command. In this case, if key is not found
|
||||
in the list, an error will result.</p>
|
||||
<p>If <i class="arg">retvar</i> is specified and <i class="arg">key</i> is in the list, then the value
|
||||
is returned in the variable <i class="arg">retvar</i> and the command returns 1 if the
|
||||
key was present within the list. If <i class="arg">key</i> isn't in the list, the
|
||||
command will return 0, and <i class="arg">retvar</i> will be left unchanged. If {} is
|
||||
specified for <i class="arg">retvar</i>, the value is not returned, allowing the Tcl
|
||||
programmer to determine if a <i class="arg">key</i> is present in a keyed list without
|
||||
setting a variable as a side-effect.</p></dd>
|
||||
<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>
|
||||
<dd><p>Return the a list of the keys in the keyed list <i class="arg">keylist</i> in the
|
||||
shared variable <i class="arg">varname</i>. If <i class="arg">key</i> is specified, then it is
|
||||
the name of a key field who's subfield keys are to be retrieved.</p></dd>
|
||||
<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>
|
||||
<dd><p>Set the value associated with <i class="arg">key</i>, in the keyed list <i class="arg">keylist</i>
|
||||
to <i class="arg">value</i>. If the <i class="arg">keylist</i> does not exists, it is created.
|
||||
If <i class="arg">key</i> is not currently in the list, it will be added. If it already
|
||||
exists, <i class="arg">value</i> replaces the existing value. Multiple keywords and
|
||||
values may be specified, if desired.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section6" class="doctools_section"><h2><a name="section6">DISCUSSION</a></h2>
|
||||
<p>The current implementation of thread shared variables allows for easy and
|
||||
convenient access to data shared between different threads.
|
||||
Internally, the data is stored in Tcl objects and all package commands
|
||||
operate on internal data representation, thus minimizing shimmering and
|
||||
improving performance. Special care has been taken to assure that all
|
||||
object data is properly locked and deep-copied when moving objects between
|
||||
threads.</p>
|
||||
<p>Due to the internal design of the Tcl core, there is no provision of full
|
||||
integration of shared variables within the Tcl syntax, unfortunately. All
|
||||
access to shared data must be performed with the supplied package commands.
|
||||
Also, variable traces are not supported. But even so, benefits of easy,
|
||||
simple and safe shared data manipulation outweights imposed limitations.</p>
|
||||
</div>
|
||||
<div id="section7" class="doctools_section"><h2><a name="section7">CREDITS</a></h2>
|
||||
<p>Thread shared variables are inspired by the nsv interface found in
|
||||
AOLserver, a highly scalable Web server from America Online.</p>
|
||||
</div>
|
||||
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
|
||||
<p>thread, tpool, ttrace</p>
|
||||
</div>
|
||||
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
|
||||
<p>locking, synchronization, thread shared data, threads</p>
|
||||
</div>
|
||||
</div></body></html>
|
||||
|
||||
312
pkgs/thread2.8.7/doc/html/ttrace.html
Normal file
312
pkgs/thread2.8.7/doc/html/ttrace.html
Normal file
@@ -0,0 +1,312 @@
|
||||
|
||||
<html><head>
|
||||
<title>ttrace - Tcl Threading</title>
|
||||
<style type="text/css"><!--
|
||||
HTML {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
BODY {
|
||||
background: #FFFFFF;
|
||||
color: black;
|
||||
}
|
||||
DIV.doctools {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
DIV.doctools H1,DIV.doctools H2 {
|
||||
margin-left: -5%;
|
||||
}
|
||||
H1, H2, H3, H4 {
|
||||
margin-top: 1em;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
color: #005A9C;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
}
|
||||
H1.doctools_title {
|
||||
text-align: center;
|
||||
}
|
||||
UL,OL {
|
||||
margin-right: 0em;
|
||||
margin-top: 3pt;
|
||||
margin-bottom: 3pt;
|
||||
}
|
||||
UL LI {
|
||||
list-style: disc;
|
||||
}
|
||||
OL LI {
|
||||
list-style: decimal;
|
||||
}
|
||||
DT {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
|
||||
font: normal 12pt/14pt sans-serif;
|
||||
list-style: none;
|
||||
}
|
||||
LI.doctools_section, LI.doctools_subsection {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
PRE {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
margin: 0%;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0.5ex;
|
||||
padding-left: 1ex;
|
||||
padding-right: 1ex;
|
||||
width: 100%;
|
||||
}
|
||||
PRE.doctools_example {
|
||||
color: black;
|
||||
background: #f5dcb3;
|
||||
border: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements LI, UL.doctools_syntax LI {
|
||||
list-style: none;
|
||||
margin-left: 0em;
|
||||
text-indent: 0em;
|
||||
padding: 0em;
|
||||
}
|
||||
DIV.doctools_synopsis {
|
||||
color: black;
|
||||
background: #80ffff;
|
||||
border: 1px solid black;
|
||||
font-family: serif;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
UL.doctools_syntax {
|
||||
margin-top: 1em;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
UL.doctools_requirements {
|
||||
margin-bottom: 1em;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
--></style>
|
||||
</head>
|
||||
<! -- Generated from file '' by tcllib/doctools with format 'html'
|
||||
-->
|
||||
<! -- ttrace.n
|
||||
-->
|
||||
<body><div class="doctools">
|
||||
<h1 class="doctools_title">ttrace(n) 2.8 "Tcl Threading"</h1>
|
||||
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
|
||||
<p>ttrace - Trace-based interpreter initialization</p>
|
||||
</div>
|
||||
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
|
||||
<ul class="doctools_toc">
|
||||
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
|
||||
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
|
||||
<li class="doctools_section"><a href="#section1">Description</a></li>
|
||||
<li class="doctools_section"><a href="#section2">USER COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section3">CALLBACK COMMANDS</a></li>
|
||||
<li class="doctools_section"><a href="#section4">DISCUSSION</a></li>
|
||||
<li class="doctools_section"><a href="#see-also">See Also</a></li>
|
||||
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
|
||||
<div class="doctools_synopsis">
|
||||
<ul class="doctools_requirements">
|
||||
<li>package require <b class="pkgname">Tcl 8.4</b></li>
|
||||
<li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li>
|
||||
</ul>
|
||||
<ul class="doctools_syntax">
|
||||
<li><a href="#1"><b class="cmd">ttrace::eval</b> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li>
|
||||
<li><a href="#2"><b class="cmd">ttrace::enable</b></a></li>
|
||||
<li><a href="#3"><b class="cmd">ttrace::disable</b></a></li>
|
||||
<li><a href="#4"><b class="cmd">ttrace::cleanup</b></a></li>
|
||||
<li><a href="#5"><b class="cmd">ttrace::update</b> <span class="opt">?epoch?</span></a></li>
|
||||
<li><a href="#6"><b class="cmd">ttrace::getscript</b></a></li>
|
||||
<li><a href="#7"><b class="cmd">ttrace::atenable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
|
||||
<li><a href="#8"><b class="cmd">ttrace::atdisable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
|
||||
<li><a href="#9"><b class="cmd">ttrace::addtrace</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
|
||||
<li><a href="#10"><b class="cmd">ttrace::addscript</b> <i class="arg">name</i> <i class="arg">body</i></a></li>
|
||||
<li><a href="#11"><b class="cmd">ttrace::addresolver</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
|
||||
<li><a href="#12"><b class="cmd">ttrace::addcleanup</b> <i class="arg">body</i></a></li>
|
||||
<li><a href="#13"><b class="cmd">ttrace::addentry</b> <i class="arg">cmd</i> <i class="arg">var</i> <i class="arg">val</i></a></li>
|
||||
<li><a href="#14"><b class="cmd">ttrace::getentry</b> <i class="arg">cmd</i> <i class="arg">var</i></a></li>
|
||||
<li><a href="#15"><b class="cmd">ttrace::getentries</b> <i class="arg">cmd</i> <span class="opt">?pattern?</span></a></li>
|
||||
<li><a href="#16"><b class="cmd">ttrace::delentry</b> <i class="arg">cmd</i></a></li>
|
||||
<li><a href="#17"><b class="cmd">ttrace::preload</b> <i class="arg">cmd</i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
|
||||
<p>This package creates a framework for on-demand replication of the
|
||||
interpreter state accross threads in an multithreading application.
|
||||
It relies on the mechanics of Tcl command tracing and the Tcl
|
||||
<b class="cmd">unknown</b> command and mechanism.</p>
|
||||
<p>The package requires Tcl threading extension but can be alternatively
|
||||
used stand-alone within the AOLserver, a scalable webserver from
|
||||
America Online.</p>
|
||||
<p>In a nutshell, a short sample illustrating the usage of the ttrace
|
||||
with the Tcl threading extension:</p>
|
||||
<pre class="doctools_example">
|
||||
% package require Ttrace
|
||||
2.8.2
|
||||
% set t1 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1802800
|
||||
% ttrace::eval {proc test args {return test-[thread::id]}}
|
||||
% thread::send $t1 test
|
||||
test-tid0x1802800
|
||||
% set t2 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1804000
|
||||
% thread::send $t2 test
|
||||
test-tid0x1804000
|
||||
</pre>
|
||||
<p>As seen from above, the <b class="cmd">ttrace::eval</b> and <b class="cmd">ttrace::update</b>
|
||||
commands are used to create a thread-wide definition of a simple
|
||||
Tcl procedure and replicate that definition to all, already existing
|
||||
or later created, threads.</p>
|
||||
</div>
|
||||
<div id="section2" class="doctools_section"><h2><a name="section2">USER COMMANDS</a></h2>
|
||||
<p>This section describes user-level commands. Those commands can be
|
||||
used by script writers to control the execution of the tracing
|
||||
framework.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="1"><b class="cmd">ttrace::eval</b> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt>
|
||||
<dd><p>This command concatenates given arguments and evaluates the resulting
|
||||
Tcl command with trace framework enabled. If the command execution
|
||||
was ok, it takes necessary steps to automatically propagate the
|
||||
trace epoch change to all threads in the application.
|
||||
For AOLserver, only newly created threads actually receive the
|
||||
epoch change. For the Tcl threading extension, all threads created by
|
||||
the extension are automatically updated. If the command execution
|
||||
resulted in Tcl error, no state propagation takes place.</p>
|
||||
<p>This is the most important user-level command of the package as
|
||||
it wraps most of the commands described below. This greatly
|
||||
simplifies things, because user need to learn just this (one)
|
||||
command in order to effectively use the package. Other commands,
|
||||
as desribed below, are included mostly for the sake of completeness.</p></dd>
|
||||
<dt><a name="2"><b class="cmd">ttrace::enable</b></a></dt>
|
||||
<dd><p>Activates all registered callbacks in the framework
|
||||
and starts a new trace epoch. The trace epoch encapsulates all
|
||||
changes done to the interpreter during the time traces are activated.</p></dd>
|
||||
<dt><a name="3"><b class="cmd">ttrace::disable</b></a></dt>
|
||||
<dd><p>Deactivates all registered callbacks in the framework
|
||||
and closes the current trace epoch.</p></dd>
|
||||
<dt><a name="4"><b class="cmd">ttrace::cleanup</b></a></dt>
|
||||
<dd><p>Used to clean-up all on-demand loaded resources in the interpreter.
|
||||
It effectively brings Tcl interpreter to its pristine state.</p></dd>
|
||||
<dt><a name="5"><b class="cmd">ttrace::update</b> <span class="opt">?epoch?</span></a></dt>
|
||||
<dd><p>Used to refresh the state of the interpreter to match the optional
|
||||
trace <span class="opt">?epoch?</span>. If the optional <span class="opt">?epoch?</span> is not given, it takes
|
||||
the most recent trace epoch.</p></dd>
|
||||
<dt><a name="6"><b class="cmd">ttrace::getscript</b></a></dt>
|
||||
<dd><p>Returns a synthetized Tcl script which may be sourced in any interpreter.
|
||||
This script sets the stage for the Tcl <b class="cmd">unknown</b> command so it can
|
||||
load traced resources from the in-memory database. Normally, this command
|
||||
is automatically invoked by other higher-level commands like
|
||||
<b class="cmd">ttrace::eval</b> and <b class="cmd">ttrace::update</b>.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section3" class="doctools_section"><h2><a name="section3">CALLBACK COMMANDS</a></h2>
|
||||
<p>A word upfront: the package already includes callbacks for tracing
|
||||
following Tcl commands: <b class="cmd">proc</b>, <b class="cmd">namespace</b>, <b class="cmd">variable</b>,
|
||||
<b class="cmd">load</b>, and <b class="cmd">rename</b>. Additionaly, a set of callbacks for
|
||||
tracing resources (object, clasess) for the XOTcl v1.3.8+, an
|
||||
OO-extension to Tcl, is also provided.
|
||||
This gives a solid base for solving most of the real-life needs and
|
||||
serves as an example for people wanting to customize the package
|
||||
to cover their specific needs.</p>
|
||||
<p>Below, you can find commands for registering callbacks in the
|
||||
framework and for writing callback scripts. These callbacks are
|
||||
invoked by the framework in order to gather interpreter state
|
||||
changes, build in-memory database, perform custom-cleanups and
|
||||
various other tasks.</p>
|
||||
<dl class="doctools_definitions">
|
||||
<dt><a name="7"><b class="cmd">ttrace::atenable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated at <b class="cmd">ttrace::enable</b>.
|
||||
Registered callbacks are activated on FIFO basis. The callback
|
||||
definition includes the name of the callback, <i class="arg">cmd</i>, a list
|
||||
of callback arguments, <i class="arg">arglist</i> and the <i class="arg">body</i> of the
|
||||
callback. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl <b class="cmd">proc</b> command.</p></dd>
|
||||
<dt><a name="8"><b class="cmd">ttrace::atdisable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated at <b class="cmd">ttrace::disable</b>.
|
||||
Registered callbacks are activated on FIFO basis. The callback
|
||||
definition includes the name of the callback, <i class="arg">cmd</i>, a list
|
||||
of callback arguments, <i class="arg">arglist</i> and the <i class="arg">body</i> of the
|
||||
callback. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl <b class="cmd">proc</b> command.</p></dd>
|
||||
<dt><a name="9"><b class="cmd">ttrace::addtrace</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated for tracing the Tcl
|
||||
<b class="cmd">cmd</b> command. The callback definition includes the name of
|
||||
the Tcl command to trace, <i class="arg">cmd</i>, a list of callback arguments,
|
||||
<i class="arg">arglist</i> and the <i class="arg">body</i> of the callback. Effectively,
|
||||
this actually resembles the call interface of the standard Tcl
|
||||
<b class="cmd">proc</b> command.</p></dd>
|
||||
<dt><a name="10"><b class="cmd">ttrace::addscript</b> <i class="arg">name</i> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated for building a Tcl
|
||||
script to be passed to other interpreters. This script is
|
||||
used to set the stage for the Tcl <b class="cmd">unknown</b> command.
|
||||
Registered callbacks are activated on FIFO basis.
|
||||
The callback definition includes the name of the callback,
|
||||
<i class="arg">name</i> and the <i class="arg">body</i> of the callback.</p></dd>
|
||||
<dt><a name="11"><b class="cmd">ttrace::addresolver</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated by the overloaded Tcl
|
||||
<b class="cmd">unknown</b> command.
|
||||
Registered callbacks are activated on FIFO basis.
|
||||
This callback is used to resolve the resource and load the
|
||||
resource in the current interpreter.</p></dd>
|
||||
<dt><a name="12"><b class="cmd">ttrace::addcleanup</b> <i class="arg">body</i></a></dt>
|
||||
<dd><p>Registers Tcl callback to be activated by the <b class="cmd">trace::cleanup</b>.
|
||||
Registered callbacks are activated on FIFO basis.</p></dd>
|
||||
<dt><a name="13"><b class="cmd">ttrace::addentry</b> <i class="arg">cmd</i> <i class="arg">var</i> <i class="arg">val</i></a></dt>
|
||||
<dd><p>Adds one entry to the named in-memory database.</p></dd>
|
||||
<dt><a name="14"><b class="cmd">ttrace::getentry</b> <i class="arg">cmd</i> <i class="arg">var</i></a></dt>
|
||||
<dd><p>Returns the value of the entry from the named in-memory database.</p></dd>
|
||||
<dt><a name="15"><b class="cmd">ttrace::getentries</b> <i class="arg">cmd</i> <span class="opt">?pattern?</span></a></dt>
|
||||
<dd><p>Returns names of all entries from the named in-memory database.</p></dd>
|
||||
<dt><a name="16"><b class="cmd">ttrace::delentry</b> <i class="arg">cmd</i></a></dt>
|
||||
<dd><p>Deletes an entry from the named in-memory database.</p></dd>
|
||||
<dt><a name="17"><b class="cmd">ttrace::preload</b> <i class="arg">cmd</i></a></dt>
|
||||
<dd><p>Registers the Tcl command to be loaded in the interpreter.
|
||||
Commands registered this way will always be the part of
|
||||
the interpreter and not be on-demand loaded by the Tcl
|
||||
<b class="cmd">unknown</b> command.</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="section4" class="doctools_section"><h2><a name="section4">DISCUSSION</a></h2>
|
||||
<p>Common introspective state-replication approaches use a custom Tcl
|
||||
script to introspect the running interpreter and synthesize another
|
||||
Tcl script to replicate this state in some other interpreter.
|
||||
This package, on the contrary, uses Tcl command traces. Command
|
||||
traces are registered on selected Tcl commands, like <b class="cmd">proc</b>,
|
||||
<b class="cmd">namespace</b>, <b class="cmd">load</b> and other standard (and/or user-defined)
|
||||
Tcl commands. When activated, those traces build an in-memory
|
||||
database of created resources. This database is used as a resource
|
||||
repository for the (overloaded) Tcl <b class="cmd">unknown</b> command which
|
||||
creates the requested resource in the interpreter on demand.
|
||||
This way, users can update just one interpreter (master) in one
|
||||
thread and replicate that interpreter state (or part of it) to other
|
||||
threads/interpreters in the process.</p>
|
||||
<p>Immediate benefit of such approach is the much smaller memory footprint
|
||||
of the application and much faster thread creation. By not actually
|
||||
loading all necessary procedures (and other resources) in every thread
|
||||
at the thread initialization time, but by deffering this to the time the
|
||||
resource is actually referenced, significant improvements in both
|
||||
memory consumption and thread initialization time can be achieved. Some
|
||||
tests have shown that memory footprint of an multithreading Tcl application
|
||||
went down more than three times and thread startup time was reduced for
|
||||
about 50 times. Note that your mileage may vary.
|
||||
Other benefits include much finer control about what (and when) gets
|
||||
replicated from the master to other Tcl thread/interpreters.</p>
|
||||
</div>
|
||||
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
|
||||
<p>thread, tpool, tsv</p>
|
||||
</div>
|
||||
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
|
||||
<p>command tracing, introspection</p>
|
||||
</div>
|
||||
</div></body></html>
|
||||
|
||||
236
pkgs/thread2.8.7/doc/man.macros
Normal file
236
pkgs/thread2.8.7/doc/man.macros
Normal file
@@ -0,0 +1,236 @@
|
||||
'\" The definitions below are for supplemental macros used in Tcl/Tk
|
||||
'\" manual entries.
|
||||
'\"
|
||||
'\" .AP type name in/out ?indent?
|
||||
'\" Start paragraph describing an argument to a library procedure.
|
||||
'\" type is type of argument (int, etc.), in/out is either "in", "out",
|
||||
'\" or "in/out" to describe whether procedure reads or modifies arg,
|
||||
'\" and indent is equivalent to second arg of .IP (shouldn't ever be
|
||||
'\" needed; use .AS below instead)
|
||||
'\"
|
||||
'\" .AS ?type? ?name?
|
||||
'\" Give maximum sizes of arguments for setting tab stops. Type and
|
||||
'\" name are examples of largest possible arguments that will be passed
|
||||
'\" to .AP later. If args are omitted, default tab stops are used.
|
||||
'\"
|
||||
'\" .BS
|
||||
'\" Start box enclosure. From here until next .BE, everything will be
|
||||
'\" enclosed in one large box.
|
||||
'\"
|
||||
'\" .BE
|
||||
'\" End of box enclosure.
|
||||
'\"
|
||||
'\" .CS
|
||||
'\" Begin code excerpt.
|
||||
'\"
|
||||
'\" .CE
|
||||
'\" End code excerpt.
|
||||
'\"
|
||||
'\" .VS ?version? ?br?
|
||||
'\" Begin vertical sidebar, for use in marking newly-changed parts
|
||||
'\" of man pages. The first argument is ignored and used for recording
|
||||
'\" the version when the .VS was added, so that the sidebars can be
|
||||
'\" found and removed when they reach a certain age. If another argument
|
||||
'\" is present, then a line break is forced before starting the sidebar.
|
||||
'\"
|
||||
'\" .VE
|
||||
'\" End of vertical sidebar.
|
||||
'\"
|
||||
'\" .DS
|
||||
'\" Begin an indented unfilled display.
|
||||
'\"
|
||||
'\" .DE
|
||||
'\" End of indented unfilled display.
|
||||
'\"
|
||||
'\" .SO
|
||||
'\" Start of list of standard options for a Tk widget. The
|
||||
'\" options follow on successive lines, in four columns separated
|
||||
'\" by tabs.
|
||||
'\"
|
||||
'\" .SE
|
||||
'\" End of list of standard options for a Tk widget.
|
||||
'\"
|
||||
'\" .OP cmdName dbName dbClass
|
||||
'\" Start of description of a specific option. cmdName gives the
|
||||
'\" option's name as specified in the class command, dbName gives
|
||||
'\" the option's name in the option database, and dbClass gives
|
||||
'\" the option's class in the option database.
|
||||
'\"
|
||||
'\" .UL arg1 arg2
|
||||
'\" Print arg1 underlined, then print arg2 normally.
|
||||
'\"
|
||||
'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
|
||||
.if t .wh -1.3i ^B
|
||||
.nr ^l \n(.l
|
||||
.ad b
|
||||
'\" # Start an argument description
|
||||
.de AP
|
||||
.ie !"\\$4"" .TP \\$4
|
||||
.el \{\
|
||||
. ie !"\\$2"" .TP \\n()Cu
|
||||
. el .TP 15
|
||||
.\}
|
||||
.ta \\n()Au \\n()Bu
|
||||
.ie !"\\$3"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP (\\$3)
|
||||
.\".b
|
||||
.\}
|
||||
.el \{\
|
||||
.br
|
||||
.ie !"\\$2"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP
|
||||
.\}
|
||||
.el \{\
|
||||
\&\\fI\\$1\\fP
|
||||
.\}
|
||||
.\}
|
||||
..
|
||||
'\" # define tabbing values for .AP
|
||||
.de AS
|
||||
.nr )A 10n
|
||||
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
|
||||
.nr )B \\n()Au+15n
|
||||
.\"
|
||||
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
|
||||
.nr )C \\n()Bu+\\w'(in/out)'u+2n
|
||||
..
|
||||
.AS Tcl_Interp Tcl_CreateInterp in/out
|
||||
'\" # BS - start boxed text
|
||||
'\" # ^y = starting y location
|
||||
'\" # ^b = 1
|
||||
.de BS
|
||||
.br
|
||||
.mk ^y
|
||||
.nr ^b 1u
|
||||
.if n .nf
|
||||
.if n .ti 0
|
||||
.if n \l'\\n(.lu\(ul'
|
||||
.if n .fi
|
||||
..
|
||||
'\" # BE - end boxed text (draw box now)
|
||||
.de BE
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
.ie n \l'\\n(^lu\(ul'
|
||||
.el \{\
|
||||
.\" Draw four-sided box normally, but don't draw top of
|
||||
.\" box if the box started on an earlier page.
|
||||
.ie !\\n(^b-1 \{\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.el \}\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.\}
|
||||
.fi
|
||||
.br
|
||||
.nr ^b 0
|
||||
..
|
||||
'\" # VS - start vertical sidebar
|
||||
'\" # ^Y = starting y location
|
||||
'\" # ^v = 1 (for troff; for nroff this doesn't matter)
|
||||
.de VS
|
||||
.if !"\\$2"" .br
|
||||
.mk ^Y
|
||||
.ie n 'mc \s12\(br\s0
|
||||
.el .nr ^v 1u
|
||||
..
|
||||
'\" # VE - end of vertical sidebar
|
||||
.de VE
|
||||
.ie n 'mc
|
||||
.el \{\
|
||||
.ev 2
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
|
||||
.sp -1
|
||||
.fi
|
||||
.ev
|
||||
.\}
|
||||
.nr ^v 0
|
||||
..
|
||||
'\" # Special macro to handle page bottom: finish off current
|
||||
'\" # box/sidebar if in box/sidebar mode, then invoked standard
|
||||
'\" # page bottom macro.
|
||||
.de ^B
|
||||
.ev 2
|
||||
'ti 0
|
||||
'nf
|
||||
.mk ^t
|
||||
.if \\n(^b \{\
|
||||
.\" Draw three-sided box if this is the box's first page,
|
||||
.\" draw two sides but no top otherwise.
|
||||
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.nr ^x \\n(^tu+1v-\\n(^Yu
|
||||
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
|
||||
.\}
|
||||
.bp
|
||||
'fi
|
||||
.ev
|
||||
.if \\n(^b \{\
|
||||
.mk ^y
|
||||
.nr ^b 2
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.mk ^Y
|
||||
.\}
|
||||
..
|
||||
'\" # DS - begin display
|
||||
.de DS
|
||||
.RS
|
||||
.nf
|
||||
.sp
|
||||
..
|
||||
'\" # DE - end display
|
||||
.de DE
|
||||
.fi
|
||||
.RE
|
||||
.sp
|
||||
..
|
||||
'\" # SO - start of list of standard options
|
||||
.de SO
|
||||
.SH "STANDARD OPTIONS"
|
||||
.LP
|
||||
.nf
|
||||
.ta 5.5c 11c
|
||||
.ft B
|
||||
..
|
||||
'\" # SE - end of list of standard options
|
||||
.de SE
|
||||
.fi
|
||||
.ft R
|
||||
.LP
|
||||
See the \\fBoptions\\fR manual entry for details on the standard options.
|
||||
..
|
||||
'\" # OP - start of full description for a single option
|
||||
.de OP
|
||||
.LP
|
||||
.nf
|
||||
.ta 4c
|
||||
Command-Line Name: \\fB\\$1\\fR
|
||||
Database Name: \\fB\\$2\\fR
|
||||
Database Class: \\fB\\$3\\fR
|
||||
.fi
|
||||
.IP
|
||||
..
|
||||
'\" # CS - begin code excerpt
|
||||
.de CS
|
||||
.RS
|
||||
.nf
|
||||
.ta .25i .5i .75i 1i
|
||||
.if t .ft C
|
||||
..
|
||||
'\" # CE - end code excerpt
|
||||
.de CE
|
||||
.fi
|
||||
.if t .ft R
|
||||
.RE
|
||||
..
|
||||
.de UL
|
||||
\\$1\l'|0\(ul'\\$2
|
||||
..
|
||||
863
pkgs/thread2.8.7/doc/man/thread.n
Normal file
863
pkgs/thread2.8.7/doc/man/thread.n
Normal file
@@ -0,0 +1,863 @@
|
||||
'\"
|
||||
'\" Generated from file '' by tcllib/doctools with format 'nroff'
|
||||
'\"
|
||||
.TH "thread" n 2\&.8 "Tcl Threading"
|
||||
.\" The -*- nroff -*- definitions below are for supplemental macros used
|
||||
.\" in Tcl/Tk manual entries.
|
||||
.\"
|
||||
.\" .AP type name in/out ?indent?
|
||||
.\" Start paragraph describing an argument to a library procedure.
|
||||
.\" type is type of argument (int, etc.), in/out is either "in", "out",
|
||||
.\" or "in/out" to describe whether procedure reads or modifies arg,
|
||||
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
|
||||
.\" needed; use .AS below instead)
|
||||
.\"
|
||||
.\" .AS ?type? ?name?
|
||||
.\" Give maximum sizes of arguments for setting tab stops. Type and
|
||||
.\" name are examples of largest possible arguments that will be passed
|
||||
.\" to .AP later. If args are omitted, default tab stops are used.
|
||||
.\"
|
||||
.\" .BS
|
||||
.\" Start box enclosure. From here until next .BE, everything will be
|
||||
.\" enclosed in one large box.
|
||||
.\"
|
||||
.\" .BE
|
||||
.\" End of box enclosure.
|
||||
.\"
|
||||
.\" .CS
|
||||
.\" Begin code excerpt.
|
||||
.\"
|
||||
.\" .CE
|
||||
.\" End code excerpt.
|
||||
.\"
|
||||
.\" .VS ?version? ?br?
|
||||
.\" Begin vertical sidebar, for use in marking newly-changed parts
|
||||
.\" of man pages. The first argument is ignored and used for recording
|
||||
.\" the version when the .VS was added, so that the sidebars can be
|
||||
.\" found and removed when they reach a certain age. If another argument
|
||||
.\" is present, then a line break is forced before starting the sidebar.
|
||||
.\"
|
||||
.\" .VE
|
||||
.\" End of vertical sidebar.
|
||||
.\"
|
||||
.\" .DS
|
||||
.\" Begin an indented unfilled display.
|
||||
.\"
|
||||
.\" .DE
|
||||
.\" End of indented unfilled display.
|
||||
.\"
|
||||
.\" .SO ?manpage?
|
||||
.\" Start of list of standard options for a Tk widget. The manpage
|
||||
.\" argument defines where to look up the standard options; if
|
||||
.\" omitted, defaults to "options". The options follow on successive
|
||||
.\" lines, in three columns separated by tabs.
|
||||
.\"
|
||||
.\" .SE
|
||||
.\" End of list of standard options for a Tk widget.
|
||||
.\"
|
||||
.\" .OP cmdName dbName dbClass
|
||||
.\" Start of description of a specific option. cmdName gives the
|
||||
.\" option's name as specified in the class command, dbName gives
|
||||
.\" the option's name in the option database, and dbClass gives
|
||||
.\" the option's class in the option database.
|
||||
.\"
|
||||
.\" .UL arg1 arg2
|
||||
.\" Print arg1 underlined, then print arg2 normally.
|
||||
.\"
|
||||
.\" .QW arg1 ?arg2?
|
||||
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
|
||||
.\"
|
||||
.\" .PQ arg1 ?arg2?
|
||||
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
|
||||
.\" (for trailing punctuation) and then a closing parenthesis.
|
||||
.\"
|
||||
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
|
||||
.if t .wh -1.3i ^B
|
||||
.nr ^l \n(.l
|
||||
.ad b
|
||||
.\" # Start an argument description
|
||||
.de AP
|
||||
.ie !"\\$4"" .TP \\$4
|
||||
.el \{\
|
||||
. ie !"\\$2"" .TP \\n()Cu
|
||||
. el .TP 15
|
||||
.\}
|
||||
.ta \\n()Au \\n()Bu
|
||||
.ie !"\\$3"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP (\\$3)
|
||||
.\".b
|
||||
.\}
|
||||
.el \{\
|
||||
.br
|
||||
.ie !"\\$2"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP
|
||||
.\}
|
||||
.el \{\
|
||||
\&\\fI\\$1\\fP
|
||||
.\}
|
||||
.\}
|
||||
..
|
||||
.\" # define tabbing values for .AP
|
||||
.de AS
|
||||
.nr )A 10n
|
||||
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
|
||||
.nr )B \\n()Au+15n
|
||||
.\"
|
||||
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
|
||||
.nr )C \\n()Bu+\\w'(in/out)'u+2n
|
||||
..
|
||||
.AS Tcl_Interp Tcl_CreateInterp in/out
|
||||
.\" # BS - start boxed text
|
||||
.\" # ^y = starting y location
|
||||
.\" # ^b = 1
|
||||
.de BS
|
||||
.br
|
||||
.mk ^y
|
||||
.nr ^b 1u
|
||||
.if n .nf
|
||||
.if n .ti 0
|
||||
.if n \l'\\n(.lu\(ul'
|
||||
.if n .fi
|
||||
..
|
||||
.\" # BE - end boxed text (draw box now)
|
||||
.de BE
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
.ie n \l'\\n(^lu\(ul'
|
||||
.el \{\
|
||||
.\" Draw four-sided box normally, but don't draw top of
|
||||
.\" box if the box started on an earlier page.
|
||||
.ie !\\n(^b-1 \{\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.el \}\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.\}
|
||||
.fi
|
||||
.br
|
||||
.nr ^b 0
|
||||
..
|
||||
.\" # VS - start vertical sidebar
|
||||
.\" # ^Y = starting y location
|
||||
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
|
||||
.de VS
|
||||
.if !"\\$2"" .br
|
||||
.mk ^Y
|
||||
.ie n 'mc \s12\(br\s0
|
||||
.el .nr ^v 1u
|
||||
..
|
||||
.\" # VE - end of vertical sidebar
|
||||
.de VE
|
||||
.ie n 'mc
|
||||
.el \{\
|
||||
.ev 2
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
|
||||
.sp -1
|
||||
.fi
|
||||
.ev
|
||||
.\}
|
||||
.nr ^v 0
|
||||
..
|
||||
.\" # Special macro to handle page bottom: finish off current
|
||||
.\" # box/sidebar if in box/sidebar mode, then invoked standard
|
||||
.\" # page bottom macro.
|
||||
.de ^B
|
||||
.ev 2
|
||||
'ti 0
|
||||
'nf
|
||||
.mk ^t
|
||||
.if \\n(^b \{\
|
||||
.\" Draw three-sided box if this is the box's first page,
|
||||
.\" draw two sides but no top otherwise.
|
||||
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.nr ^x \\n(^tu+1v-\\n(^Yu
|
||||
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
|
||||
.\}
|
||||
.bp
|
||||
'fi
|
||||
.ev
|
||||
.if \\n(^b \{\
|
||||
.mk ^y
|
||||
.nr ^b 2
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.mk ^Y
|
||||
.\}
|
||||
..
|
||||
.\" # DS - begin display
|
||||
.de DS
|
||||
.RS
|
||||
.nf
|
||||
.sp
|
||||
..
|
||||
.\" # DE - end display
|
||||
.de DE
|
||||
.fi
|
||||
.RE
|
||||
.sp
|
||||
..
|
||||
.\" # SO - start of list of standard options
|
||||
.de SO
|
||||
'ie '\\$1'' .ds So \\fBoptions\\fR
|
||||
'el .ds So \\fB\\$1\\fR
|
||||
.SH "STANDARD OPTIONS"
|
||||
.LP
|
||||
.nf
|
||||
.ta 5.5c 11c
|
||||
.ft B
|
||||
..
|
||||
.\" # SE - end of list of standard options
|
||||
.de SE
|
||||
.fi
|
||||
.ft R
|
||||
.LP
|
||||
See the \\*(So manual entry for details on the standard options.
|
||||
..
|
||||
.\" # OP - start of full description for a single option
|
||||
.de OP
|
||||
.LP
|
||||
.nf
|
||||
.ta 4c
|
||||
Command-Line Name: \\fB\\$1\\fR
|
||||
Database Name: \\fB\\$2\\fR
|
||||
Database Class: \\fB\\$3\\fR
|
||||
.fi
|
||||
.IP
|
||||
..
|
||||
.\" # CS - begin code excerpt
|
||||
.de CS
|
||||
.RS
|
||||
.nf
|
||||
.ta .25i .5i .75i 1i
|
||||
..
|
||||
.\" # CE - end code excerpt
|
||||
.de CE
|
||||
.fi
|
||||
.RE
|
||||
..
|
||||
.\" # UL - underline word
|
||||
.de UL
|
||||
\\$1\l'|0\(ul'\\$2
|
||||
..
|
||||
.\" # QW - apply quotation marks to word
|
||||
.de QW
|
||||
.ie '\\*(lq'"' ``\\$1''\\$2
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\$2
|
||||
..
|
||||
.\" # PQ - apply parens and quotation marks to word
|
||||
.de PQ
|
||||
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
|
||||
..
|
||||
.\" # QR - quoted range
|
||||
.de QR
|
||||
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
|
||||
..
|
||||
.\" # MT - "empty" string
|
||||
.de MT
|
||||
.QW ""
|
||||
..
|
||||
.BS
|
||||
.SH NAME
|
||||
thread \- Extension for script access to Tcl threading
|
||||
.SH SYNOPSIS
|
||||
package require \fBTcl 8\&.4\fR
|
||||
.sp
|
||||
package require \fBThread ?2\&.8?\fR
|
||||
.sp
|
||||
\fBthread::create\fR ?-joinable? ?-preserved? ?script?
|
||||
.sp
|
||||
\fBthread::preserve\fR ?id?
|
||||
.sp
|
||||
\fBthread::release\fR ?-wait? ?id?
|
||||
.sp
|
||||
\fBthread::id\fR
|
||||
.sp
|
||||
\fBthread::errorproc\fR ?procname?
|
||||
.sp
|
||||
\fBthread::cancel\fR ?-unwind? \fIid\fR ?result?
|
||||
.sp
|
||||
\fBthread::unwind\fR
|
||||
.sp
|
||||
\fBthread::exit\fR ?status?
|
||||
.sp
|
||||
\fBthread::names\fR
|
||||
.sp
|
||||
\fBthread::exists\fR \fIid\fR
|
||||
.sp
|
||||
\fBthread::send\fR ?-async? ?-head? \fIid\fR \fIscript\fR ?varname?
|
||||
.sp
|
||||
\fBthread::broadcast\fR \fIscript\fR
|
||||
.sp
|
||||
\fBthread::wait\fR
|
||||
.sp
|
||||
\fBthread::eval\fR ?-lock mutex? \fIarg\fR ?arg \&.\&.\&.?
|
||||
.sp
|
||||
\fBthread::join\fR \fIid\fR
|
||||
.sp
|
||||
\fBthread::configure\fR \fIid\fR ?option? ?value? ?\&.\&.\&.?
|
||||
.sp
|
||||
\fBthread::transfer\fR \fIid\fR \fIchannel\fR
|
||||
.sp
|
||||
\fBthread::detach\fR \fIchannel\fR
|
||||
.sp
|
||||
\fBthread::attach\fR \fIchannel\fR
|
||||
.sp
|
||||
\fBthread::mutex\fR
|
||||
.sp
|
||||
\fBthread::mutex\fR \fBcreate\fR ?-recursive?
|
||||
.sp
|
||||
\fBthread::mutex\fR \fBdestroy\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::mutex\fR \fBlock\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::mutex\fR \fBunlock\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR \fBcreate\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR \fBdestroy\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR \fBrlock\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR \fBwlock\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::rwmutex\fR \fBunlock\fR \fImutex\fR
|
||||
.sp
|
||||
\fBthread::cond\fR
|
||||
.sp
|
||||
\fBthread::cond\fR \fBcreate\fR
|
||||
.sp
|
||||
\fBthread::cond\fR \fBdestroy\fR \fIcond\fR
|
||||
.sp
|
||||
\fBthread::cond\fR \fBnotify\fR \fIcond\fR
|
||||
.sp
|
||||
\fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms?
|
||||
.sp
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
The \fBthread\fR extension creates threads that contain Tcl
|
||||
interpreters, and it lets you send scripts to those threads for
|
||||
evaluation\&.
|
||||
Additionally, it provides script-level access to basic thread
|
||||
synchronization primitives, like mutexes and condition variables\&.
|
||||
.SH COMMANDS
|
||||
This section describes commands for creating and destroying threads
|
||||
and sending scripts to threads for evaluation\&.
|
||||
.TP
|
||||
\fBthread::create\fR ?-joinable? ?-preserved? ?script?
|
||||
This command creates a thread that contains a Tcl interpreter\&.
|
||||
The Tcl interpreter either evaluates the optional \fBscript\fR, if
|
||||
specified, or it waits in the event loop for scripts that arrive via
|
||||
the \fBthread::send\fR command\&. Both of them would take place simultaneously
|
||||
with the return of command \fBthread::create\fR to the caller thread\&.
|
||||
Neither the caller is waiting for the finishing of optional \fBscript\fR,
|
||||
nor the result, if any, of the \fBscript\fR is returned to the caller\&.
|
||||
The result of \fBthread::create\fR is the ID of the thread\&. This is
|
||||
the opaque handle which identifies the newly created thread for
|
||||
all other package commands\&. The handle of the thread goes out of scope
|
||||
automatically when thread is marked for exit
|
||||
(see the \fBthread::release\fR command below)\&.
|
||||
.sp
|
||||
If the optional \fBscript\fR argument contains the \fBthread::wait\fR
|
||||
command the thread will enter into the event loop\&. If such command is not
|
||||
found in the \fBscript\fR the thread will run the \fBscript\fR to
|
||||
the end and exit\&. In that case, the handle may be safely ignored since it
|
||||
refers to a thread which does not exists any more at the time when the
|
||||
command returns\&.
|
||||
.sp
|
||||
Using flag \fB-joinable\fR it is possible to create a joinable
|
||||
thread, i\&.e\&. one upon whose exit can be waited upon by using
|
||||
\fBthread::join\fR command\&.
|
||||
Note that failure to join a thread created with \fB-joinable\fR flag
|
||||
results in resource and memory leaks\&.
|
||||
.sp
|
||||
Threads created by the \fBthread::create\fR cannot be destroyed
|
||||
forcefully\&. Consequently, there is no corresponding thread destroy
|
||||
command\&. A thread may only be released using the \fBthread::release\fR
|
||||
and if its internal reference count drops to zero, the thread is
|
||||
marked for exit\&. This kicks the thread out of the event loop
|
||||
servicing and the thread continues to execute commands passed in
|
||||
the \fBscript\fR argument, following the \fBthread::wait\fR
|
||||
command\&. If this was the last command in the script, as usually the
|
||||
case, the thread will exit\&.
|
||||
.sp
|
||||
It is possible to create a situation in which it may be impossible
|
||||
to terminate the thread, for example by putting some endless loop
|
||||
after the \fBthread::wait\fR or entering the event loop again by
|
||||
doing an vwait-type of command\&. In such cases, the thread may never
|
||||
exit\&. This is considered to be a bad practice and should be avoided
|
||||
if possible\&. This is best illustrated by the example below:
|
||||
.CS
|
||||
|
||||
|
||||
# You should never do \&.\&.\&.
|
||||
set tid [thread::create {
|
||||
package require Http
|
||||
thread::wait
|
||||
vwait forever ; # <-- this!
|
||||
}]
|
||||
|
||||
.CE
|
||||
.IP
|
||||
The thread created in the above example will never be able to exit\&.
|
||||
After it has been released with the last matching \fBthread::release\fR
|
||||
call, the thread will jump out of the \fBthread::wait\fR and continue
|
||||
to execute commands following\&. It will enter \fBvwait\fR command and
|
||||
wait endlessly for events\&. There is no way one can terminate such thread,
|
||||
so you wouldn't want to do this!
|
||||
.sp
|
||||
Each newly created has its internal reference counter set to 0 (zero),
|
||||
i\&.e\&. it is unreserved\&. This counter gets incremented by a call to
|
||||
\fBthread::preserve\fR and decremented by a call to \fBthread::release\fR
|
||||
command\&. These two commands implement simple but effective thread
|
||||
reservation system and offer predictable and controllable thread
|
||||
termination capabilities\&. It is however possible to create initially
|
||||
preserved threads by using flag \fB-preserved\fR of the
|
||||
\fBthread::create\fR command\&. Threads created with this flag have the
|
||||
initial value of the reference counter of 1 (one), and are thus
|
||||
initially marked reserved\&.
|
||||
.TP
|
||||
\fBthread::preserve\fR ?id?
|
||||
This command increments the thread reference counter\&. Each call
|
||||
to this command increments the reference counter by one (1)\&.
|
||||
Command returns the value of the reference counter after the increment\&.
|
||||
If called with the optional thread \fBid\fR, the command preserves
|
||||
the given thread\&. Otherwise the current thread is preserved\&.
|
||||
.sp
|
||||
With reference counting, one can implement controlled access to a
|
||||
shared Tcl thread\&. By incrementing the reference counter, the
|
||||
caller signalizes that he/she wishes to use the thread for a longer
|
||||
period of time\&. By decrementing the counter, caller signalizes that
|
||||
he/she has finished using the thread\&.
|
||||
.TP
|
||||
\fBthread::release\fR ?-wait? ?id?
|
||||
This command decrements the thread reference counter\&. Each call to
|
||||
this command decrements the reference counter by one (1)\&.
|
||||
If called with the optional thread \fBid\fR, the command releases
|
||||
the given thread\&. Otherwise, the current thread is released\&.
|
||||
Command returns the value of the reference counter after the decrement\&.
|
||||
When the reference counter reaches zero (0), the target thread is
|
||||
marked for termination\&. You should not reference the thread after the
|
||||
\fBthread::release\fR command returns zero or negative integer\&.
|
||||
The handle of the thread goes out of scope and should not be used any
|
||||
more\&. Any following reference to the same thread handle will result
|
||||
in Tcl error\&.
|
||||
.sp
|
||||
Optional flag \fB-wait\fR instructs the caller thread to wait for
|
||||
the target thread to exit, if the effect of the command would result
|
||||
in termination of the target thread, i\&.e\&. if the return result would
|
||||
be zero (0)\&. Without the flag, the caller thread does not wait for
|
||||
the target thread to exit\&. Care must be taken when using the
|
||||
\fB-wait\fR, since this may block the caller thread indefinitely\&.
|
||||
This option has been implemented for some special uses of the extension
|
||||
and is deprecated for regular use\&. Regular users should create joinable
|
||||
threads by using the \fB-joinable\fR option of the \fBthread::create\fR
|
||||
command and the \fBthread::join\fR to wait for thread to exit\&.
|
||||
.TP
|
||||
\fBthread::id\fR
|
||||
This command returns the ID of the current thread\&.
|
||||
.TP
|
||||
\fBthread::errorproc\fR ?procname?
|
||||
This command sets a handler for errors that occur in scripts sent
|
||||
asynchronously, using the \fB-async\fR flag of the
|
||||
\fBthread::send\fR command, to other threads\&. If no handler
|
||||
is specified, the current handler is returned\&. The empty string
|
||||
resets the handler to default (unspecified) value\&.
|
||||
An uncaught error in a thread causes an error message to be sent
|
||||
to the standard error channel\&. This default reporting scheme can
|
||||
be changed by registering a procedure which is called to report
|
||||
the error\&. The \fIprocname\fR is called in the interpreter that
|
||||
invoked the \fBthread::errorproc\fR command\&. The \fIprocname\fR
|
||||
is called like this:
|
||||
.CS
|
||||
|
||||
|
||||
myerrorproc thread_id errorInfo
|
||||
|
||||
.CE
|
||||
.TP
|
||||
\fBthread::cancel\fR ?-unwind? \fIid\fR ?result?
|
||||
This command requires Tcl version 8\&.6 or higher\&.
|
||||
.sp
|
||||
Cancels the script being evaluated in the thread given by the \fIid\fR
|
||||
parameter\&. Without the \fB-unwind\fR switch the evaluation stack for
|
||||
the interpreter is unwound until an enclosing catch command is found or
|
||||
there are no further invocations of the interpreter left on the call
|
||||
stack\&. With the \fB-unwind\fR switch the evaluation stack for the
|
||||
interpreter is unwound without regard to any intervening catch command
|
||||
until there are no further invocations of the interpreter left on the
|
||||
call stack\&. If \fIresult\fR is present, it will be used as the error
|
||||
message string; otherwise, a default error message string will be used\&.
|
||||
.TP
|
||||
\fBthread::unwind\fR
|
||||
Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with \fBthread::preserve\fR and
|
||||
\fBthread::release\fR commands\&. Support for \fBthread::unwind\fR
|
||||
command will disappear in some future major release of the extension\&.
|
||||
.sp
|
||||
This command stops a prior \fBthread::wait\fR command\&. Execution of
|
||||
the script passed to newly created thread will continue from the
|
||||
\fBthread::wait\fR command\&. If \fBthread::wait\fR was the last command
|
||||
in the script, the thread will exit\&. The command returns empty result
|
||||
but may trigger Tcl error with the message "target thread died" in some
|
||||
situations\&.
|
||||
.TP
|
||||
\fBthread::exit\fR ?status?
|
||||
Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with \fBthread::preserve\fR and
|
||||
\fBthread::release\fR commands\&. Support for \fBthread::exit\fR
|
||||
command will disappear in some future major release of the extension\&.
|
||||
.sp
|
||||
This command forces a thread stuck in the \fBthread::wait\fR command to
|
||||
unconditionally exit\&. The thread's exit status defaults to 666 and can be
|
||||
specified using the optional \fIstatus\fR argument\&. The execution of
|
||||
\fBthread::exit\fR command is guaranteed to leave the program memory in the
|
||||
inconsistent state, produce memory leaks and otherwise affect other subsystem(s)
|
||||
of the Tcl application in an unpredictable manner\&. The command returns empty
|
||||
result but may trigger Tcl error with the message "target thread died" in some
|
||||
situations\&.
|
||||
.TP
|
||||
\fBthread::names\fR
|
||||
This command returns a list of thread IDs\&. These are only for
|
||||
threads that have been created via \fBthread::create\fR command\&.
|
||||
If your application creates other threads at the C level, they
|
||||
are not reported by this command\&.
|
||||
.TP
|
||||
\fBthread::exists\fR \fIid\fR
|
||||
Returns true (1) if thread given by the \fIid\fR parameter exists,
|
||||
false (0) otherwise\&. This applies only for threads that have
|
||||
been created via \fBthread::create\fR command\&.
|
||||
.TP
|
||||
\fBthread::send\fR ?-async? ?-head? \fIid\fR \fIscript\fR ?varname?
|
||||
This command passes a \fIscript\fR to another thread and, optionally,
|
||||
waits for the result\&. If the \fB-async\fR flag is specified, the
|
||||
command does not wait for the result and it returns empty string\&.
|
||||
The target thread must enter it's event loop in order to receive
|
||||
scripts sent via this command\&. This is done by default for threads
|
||||
created without a startup script\&. Threads can enter the event loop
|
||||
explicitly by calling \fBthread::wait\fR or any other relevant Tcl/Tk
|
||||
command, like \fBupdate\fR, \fBvwait\fR, etc\&.
|
||||
.sp
|
||||
Optional \fBvarname\fR specifies name of the variable to store
|
||||
the result of the \fIscript\fR\&. Without the \fB-async\fR flag,
|
||||
the command returns the evaluation code, similarly to the standard
|
||||
Tcl \fBcatch\fR command\&. If, however, the \fB-async\fR flag is
|
||||
specified, the command returns immediately and caller can later
|
||||
\fBvwait\fR on ?varname? to get the result of the passed \fIscript\fR
|
||||
.CS
|
||||
|
||||
|
||||
set t1 [thread::create]
|
||||
set t2 [thread::create]
|
||||
thread::send -async $t1 "set a 1" result
|
||||
thread::send -async $t2 "set b 2" result
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
vwait result
|
||||
}
|
||||
|
||||
.CE
|
||||
.IP
|
||||
In the above example, two threads were fed work and both of them were
|
||||
instructed to signalize the same variable "result" in the calling thread\&.
|
||||
The caller entered the event loop twice to get both results\&. Note,
|
||||
however, that the order of the received results may vary, depending on
|
||||
the current system load, type of work done, etc, etc\&.
|
||||
.sp
|
||||
Many threads can simultaneously send scripts to the target thread for
|
||||
execution\&. All of them are entered into the event queue of the target
|
||||
thread and executed on the FIFO basis, intermingled with optional other
|
||||
events pending in the event queue of the target thread\&.
|
||||
Using the optional ?-head? switch, scripts posted to the thread's
|
||||
event queue can be placed on the head, instead on the tail of the queue,
|
||||
thus being executed in the LIFO fashion\&.
|
||||
.TP
|
||||
\fBthread::broadcast\fR \fIscript\fR
|
||||
This command passes a \fIscript\fR to all threads created by the
|
||||
package for execution\&. It does not wait for response from any of
|
||||
the threads\&.
|
||||
.TP
|
||||
\fBthread::wait\fR
|
||||
This enters the event loop so a thread can receive messages from
|
||||
the \fBthread::send\fR command\&. This command should only be used
|
||||
within the script passed to the \fBthread::create\fR\&. It should
|
||||
be the very last command in the script\&. If this is not the case,
|
||||
the exiting thread will continue executing the script lines past
|
||||
the \fBthread::wait\fR which is usually not what you want and/or
|
||||
expect\&.
|
||||
.CS
|
||||
|
||||
|
||||
set t1 [thread::create {
|
||||
#
|
||||
# Do some initialization work here
|
||||
#
|
||||
thread::wait ; # Enter the event loop
|
||||
}]
|
||||
|
||||
.CE
|
||||
.TP
|
||||
\fBthread::eval\fR ?-lock mutex? \fIarg\fR ?arg \&.\&.\&.?
|
||||
This command concatenates passed arguments and evaluates the
|
||||
resulting script under the mutex protection\&. If no mutex is
|
||||
specified by using the ?-lock mutex? optional argument,
|
||||
the internal static mutex is used\&.
|
||||
.TP
|
||||
\fBthread::join\fR \fIid\fR
|
||||
This command waits for the thread with ID \fIid\fR to exit and
|
||||
then returns it's exit code\&. Errors will be returned for threads
|
||||
which are not joinable or already waited upon by another thread\&.
|
||||
Upon the join the handle of the thread has gone out of scope and
|
||||
should not be used any more\&.
|
||||
.TP
|
||||
\fBthread::configure\fR \fIid\fR ?option? ?value? ?\&.\&.\&.?
|
||||
This command configures various low-level aspects of the thread with
|
||||
ID \fIid\fR in the similar way as the standard Tcl command
|
||||
\fBfconfigure\fR configures some Tcl channel options\&. Options currently
|
||||
supported are: \fB-eventmark\fR and \fB-unwindonerror\fR\&.
|
||||
.sp
|
||||
When \fB-eventmark\fR is provided with a value greater than 0 (zero), that
|
||||
value is the maximum number of asynchronously posted scripts that may be
|
||||
pending for the thread\&. \fBthread::send -async\fR blocks until the number of
|
||||
pending scripts in the event loop drops below the \fB-eventmark\fR value\&.
|
||||
.sp
|
||||
When \fB-unwindonerror\fR is provided with a value of true, an error result
|
||||
in a script causes the thread to unwind, making it unavailable to evaluate
|
||||
additional scripts\&.
|
||||
.TP
|
||||
\fBthread::transfer\fR \fIid\fR \fIchannel\fR
|
||||
This moves the specified \fIchannel\fR from the current thread
|
||||
and interpreter to the main interpreter of the thread with the
|
||||
given \fIid\fR\&. After the move the current interpreter has no
|
||||
access to the channel any more, but the main interpreter of the
|
||||
target thread will be able to use it from now on\&.
|
||||
The command waits until the other thread has incorporated the
|
||||
channel\&. Because of this it is possible to deadlock the
|
||||
participating threads by commanding the other through a
|
||||
synchronous \fBthread::send\fR to transfer a channel to us\&.
|
||||
This easily extends into longer loops of threads waiting for
|
||||
each other\&. Other restrictions: the channel in question must
|
||||
not be shared among multiple interpreters running in the
|
||||
sending thread\&. This automatically excludes the special channels
|
||||
for standard input, output and error\&.
|
||||
.sp
|
||||
Due to the internal Tcl core implementation and the restriction on
|
||||
transferring shared channels, one has to take extra measures when
|
||||
transferring socket channels created by accepting the connection
|
||||
out of the \fBsocket\fR commands callback procedures:
|
||||
.CS
|
||||
|
||||
|
||||
socket -server _Accept 2200
|
||||
proc _Accept {s ipaddr port} {
|
||||
after idle [list Accept $s $ipaddr $port]
|
||||
}
|
||||
proc Accept {s ipaddr port} {
|
||||
set tid [thread::create]
|
||||
thread::transfer $tid $s
|
||||
}
|
||||
|
||||
.CE
|
||||
.TP
|
||||
\fBthread::detach\fR \fIchannel\fR
|
||||
This detaches the specified \fIchannel\fR from the current thread and
|
||||
interpreter\&. After that, the current interpreter has no access to the
|
||||
channel any more\&. The channel is in the parked state until some other
|
||||
(or the same) thread attaches the channel again with \fBthread::attach\fR\&.
|
||||
Restrictions: same as for transferring shared channels with the
|
||||
\fBthread::transfer\fR command\&.
|
||||
.TP
|
||||
\fBthread::attach\fR \fIchannel\fR
|
||||
This attaches the previously detached \fIchannel\fR in the
|
||||
current thread/interpreter\&. For already existing channels,
|
||||
the command does nothing, i\&.e\&. it is not an error to attach the
|
||||
same channel more than once\&. The first operation will actually
|
||||
perform the operation, while all subsequent operation will just
|
||||
do nothing\&. Command throws error if the \fIchannel\fR cannot be
|
||||
found in the list of detached channels and/or in the current
|
||||
interpreter\&.
|
||||
.TP
|
||||
\fBthread::mutex\fR
|
||||
Mutexes are most common thread synchronization primitives\&.
|
||||
They are used to synchronize access from two or more threads to one or
|
||||
more shared resources\&. This command provides script-level access to
|
||||
exclusive and/or recursive mutexes\&. Exclusive mutexes can be locked
|
||||
only once by one thread, while recursive mutexes can be locked many
|
||||
times by the same thread\&. For recursive mutexes, number of lock and
|
||||
unlock operations must match, otherwise, the mutex will never be
|
||||
released, which would lead to various deadlock situations\&.
|
||||
.sp
|
||||
Care has to be taken when using mutexes in an multithreading program\&.
|
||||
Improper use of mutexes may lead to various deadlock situations,
|
||||
especially when using exclusive mutexes\&.
|
||||
.sp
|
||||
The \fBthread::mutex\fR command supports following subcommands and options:
|
||||
.RS
|
||||
.TP
|
||||
\fBthread::mutex\fR \fBcreate\fR ?-recursive?
|
||||
Creates the mutex and returns it's opaque handle\&. This handle
|
||||
should be used for any future reference to the newly created mutex\&.
|
||||
If no optional ?-recursive? argument was specified, the command
|
||||
creates the exclusive mutex\&. With the ?-recursive? argument,
|
||||
the command creates a recursive mutex\&.
|
||||
.TP
|
||||
\fBthread::mutex\fR \fBdestroy\fR \fImutex\fR
|
||||
Destroys the \fImutex\fR\&. Mutex should be in unlocked state before
|
||||
the destroy attempt\&. If the mutex is locked, the command will throw
|
||||
Tcl error\&.
|
||||
.TP
|
||||
\fBthread::mutex\fR \fBlock\fR \fImutex\fR
|
||||
Locks the \fImutex\fR\&. Locking the exclusive mutex may throw Tcl
|
||||
error if on attempt to lock the same mutex twice from the same
|
||||
thread\&. If your program logic forces you to lock the same mutex
|
||||
twice or more from the same thread (this may happen in recursive
|
||||
procedure invocations) you should consider using the recursive mutexes\&.
|
||||
.TP
|
||||
\fBthread::mutex\fR \fBunlock\fR \fImutex\fR
|
||||
Unlocks the \fImutex\fR so some other thread may lock it again\&.
|
||||
Attempt to unlock the already unlocked mutex will throw Tcl error\&.
|
||||
.RE
|
||||
.sp
|
||||
.TP
|
||||
\fBthread::rwmutex\fR
|
||||
This command creates many-readers/single-writer mutexes\&. Reader/writer
|
||||
mutexes allow you to serialize access to a shared resource more optimally\&.
|
||||
In situations where a shared resource gets mostly read and seldom modified,
|
||||
you might gain some performance by using reader/writer mutexes instead of
|
||||
exclusive or recursive mutexes\&.
|
||||
.sp
|
||||
For reading the resource, thread should obtain a read lock on the resource\&.
|
||||
Read lock is non-exclusive, meaning that more than one thread can
|
||||
obtain a read lock to the same resource, without waiting on other readers\&.
|
||||
For changing the resource, however, a thread must obtain a exclusive
|
||||
write lock\&. This lock effectively blocks all threads from gaining the
|
||||
read-lock while the resource is been modified by the writer thread\&.
|
||||
Only after the write lock has been released, the resource may be read-locked
|
||||
again\&.
|
||||
.sp
|
||||
The \fBthread::rwmutex\fR command supports following subcommands and options:
|
||||
.RS
|
||||
.TP
|
||||
\fBthread::rwmutex\fR \fBcreate\fR
|
||||
Creates the reader/writer mutex and returns it's opaque handle\&.
|
||||
This handle should be used for any future reference to the newly
|
||||
created mutex\&.
|
||||
.TP
|
||||
\fBthread::rwmutex\fR \fBdestroy\fR \fImutex\fR
|
||||
Destroys the reader/writer \fImutex\fR\&. If the mutex is already locked,
|
||||
attempt to destroy it will throw Tcl error\&.
|
||||
.TP
|
||||
\fBthread::rwmutex\fR \fBrlock\fR \fImutex\fR
|
||||
Locks the \fImutex\fR for reading\&. More than one thread may read-lock
|
||||
the same \fImutex\fR at the same time\&.
|
||||
.TP
|
||||
\fBthread::rwmutex\fR \fBwlock\fR \fImutex\fR
|
||||
Locks the \fImutex\fR for writing\&. Only one thread may write-lock
|
||||
the same \fImutex\fR at the same time\&. Attempt to write-lock same
|
||||
\fImutex\fR twice from the same thread will throw Tcl error\&.
|
||||
.TP
|
||||
\fBthread::rwmutex\fR \fBunlock\fR \fImutex\fR
|
||||
Unlocks the \fImutex\fR so some other thread may lock it again\&.
|
||||
Attempt to unlock already unlocked \fImutex\fR will throw Tcl error\&.
|
||||
.RE
|
||||
.sp
|
||||
.TP
|
||||
\fBthread::cond\fR
|
||||
This command provides script-level access to condition variables\&.
|
||||
A condition variable creates a safe environment for the program
|
||||
to test some condition, sleep on it when false and be awakened
|
||||
when it might have become true\&. A condition variable is always
|
||||
used in the conjunction with an exclusive mutex\&. If you attempt
|
||||
to use other type of mutex in conjunction with the condition
|
||||
variable, a Tcl error will be thrown\&.
|
||||
.sp
|
||||
The command supports following subcommands and options:
|
||||
.RS
|
||||
.TP
|
||||
\fBthread::cond\fR \fBcreate\fR
|
||||
Creates the condition variable and returns it's opaque handle\&.
|
||||
This handle should be used for any future reference to newly
|
||||
created condition variable\&.
|
||||
.TP
|
||||
\fBthread::cond\fR \fBdestroy\fR \fIcond\fR
|
||||
Destroys condition variable \fIcond\fR\&. Extreme care has to be taken
|
||||
that nobody is using (i\&.e\&. waiting on) the condition variable,
|
||||
otherwise unexpected errors may happen\&.
|
||||
.TP
|
||||
\fBthread::cond\fR \fBnotify\fR \fIcond\fR
|
||||
Wakes up all threads waiting on the condition variable \fIcond\fR\&.
|
||||
.TP
|
||||
\fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms?
|
||||
This command is used to suspend program execution until the condition
|
||||
variable \fIcond\fR has been signalled or the optional timer has expired\&.
|
||||
The exclusive \fImutex\fR must be locked by the calling thread on entrance
|
||||
to this command\&. If the mutex is not locked, Tcl error is thrown\&.
|
||||
While waiting on the \fIcond\fR, the command releases \fImutex\fR\&.
|
||||
Before returning to the calling thread, the command re-acquires the
|
||||
\fImutex\fR again\&. Unlocking the \fImutex\fR and waiting on the
|
||||
condition variable \fIcond\fR is done atomically\&.
|
||||
.sp
|
||||
The \fBms\fR command option, if given, must be an integer specifying
|
||||
time interval in milliseconds the command waits to be signalled\&.
|
||||
Otherwise the command waits on condition notify forever\&.
|
||||
.sp
|
||||
In multithreading programs, there are many situations where a thread has
|
||||
to wait for some event to happen until it is allowed to proceed\&.
|
||||
This is usually accomplished by repeatedly testing a condition under the
|
||||
mutex protection and waiting on the condition variable until the condition
|
||||
evaluates to true:
|
||||
.CS
|
||||
|
||||
|
||||
set mutex [thread::mutex create]
|
||||
set cond [thread::cond create]
|
||||
|
||||
thread::mutex lock $mutex
|
||||
while {<some_condition_is_true>} {
|
||||
thread::cond wait $cond $mutex
|
||||
}
|
||||
# Do some work under mutex protection
|
||||
thread::mutex unlock $mutex
|
||||
|
||||
.CE
|
||||
.IP
|
||||
Repeated testing of the condition is needed since the condition variable
|
||||
may get signalled without the condition being actually changed (spurious
|
||||
thread wake-ups, for example)\&.
|
||||
.RE
|
||||
.PP
|
||||
.SH DISCUSSION
|
||||
The fundamental threading model in Tcl is that there can be one or
|
||||
more Tcl interpreters per thread, but each Tcl interpreter should
|
||||
only be used by a single thread which created it\&.
|
||||
A "shared memory" abstraction is awkward to provide in Tcl because
|
||||
Tcl makes assumptions about variable and data ownership\&. Therefore
|
||||
this extension supports a simple form of threading where the main
|
||||
thread can manage several background, or "worker" threads\&.
|
||||
For example, an event-driven server can pass requests to worker
|
||||
threads, and then await responses from worker threads or new client
|
||||
requests\&. Everything goes through the common Tcl event loop, so
|
||||
message passing between threads works naturally with event-driven I/O,
|
||||
\fBvwait\fR on variables, and so forth\&. For the transfer of bulk
|
||||
information it is possible to move channels between the threads\&.
|
||||
.PP
|
||||
For advanced multithreading scripts, script-level access to two
|
||||
basic synchronization primitives, mutex and condition variables,
|
||||
is also supported\&.
|
||||
.SH "SEE ALSO"
|
||||
\fIhttp://www\&.tcl\&.tk/doc/howto/thread_model\&.html\fR, tpool, tsv, ttrace
|
||||
.SH KEYWORDS
|
||||
events, message passing, mutex, synchronization, thread
|
||||
496
pkgs/thread2.8.7/doc/man/tpool.n
Normal file
496
pkgs/thread2.8.7/doc/man/tpool.n
Normal file
@@ -0,0 +1,496 @@
|
||||
'\"
|
||||
'\" Generated from file '' by tcllib/doctools with format 'nroff'
|
||||
'\"
|
||||
.TH "tpool" n 2\&.8 "Tcl Threading"
|
||||
.\" The -*- nroff -*- definitions below are for supplemental macros used
|
||||
.\" in Tcl/Tk manual entries.
|
||||
.\"
|
||||
.\" .AP type name in/out ?indent?
|
||||
.\" Start paragraph describing an argument to a library procedure.
|
||||
.\" type is type of argument (int, etc.), in/out is either "in", "out",
|
||||
.\" or "in/out" to describe whether procedure reads or modifies arg,
|
||||
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
|
||||
.\" needed; use .AS below instead)
|
||||
.\"
|
||||
.\" .AS ?type? ?name?
|
||||
.\" Give maximum sizes of arguments for setting tab stops. Type and
|
||||
.\" name are examples of largest possible arguments that will be passed
|
||||
.\" to .AP later. If args are omitted, default tab stops are used.
|
||||
.\"
|
||||
.\" .BS
|
||||
.\" Start box enclosure. From here until next .BE, everything will be
|
||||
.\" enclosed in one large box.
|
||||
.\"
|
||||
.\" .BE
|
||||
.\" End of box enclosure.
|
||||
.\"
|
||||
.\" .CS
|
||||
.\" Begin code excerpt.
|
||||
.\"
|
||||
.\" .CE
|
||||
.\" End code excerpt.
|
||||
.\"
|
||||
.\" .VS ?version? ?br?
|
||||
.\" Begin vertical sidebar, for use in marking newly-changed parts
|
||||
.\" of man pages. The first argument is ignored and used for recording
|
||||
.\" the version when the .VS was added, so that the sidebars can be
|
||||
.\" found and removed when they reach a certain age. If another argument
|
||||
.\" is present, then a line break is forced before starting the sidebar.
|
||||
.\"
|
||||
.\" .VE
|
||||
.\" End of vertical sidebar.
|
||||
.\"
|
||||
.\" .DS
|
||||
.\" Begin an indented unfilled display.
|
||||
.\"
|
||||
.\" .DE
|
||||
.\" End of indented unfilled display.
|
||||
.\"
|
||||
.\" .SO ?manpage?
|
||||
.\" Start of list of standard options for a Tk widget. The manpage
|
||||
.\" argument defines where to look up the standard options; if
|
||||
.\" omitted, defaults to "options". The options follow on successive
|
||||
.\" lines, in three columns separated by tabs.
|
||||
.\"
|
||||
.\" .SE
|
||||
.\" End of list of standard options for a Tk widget.
|
||||
.\"
|
||||
.\" .OP cmdName dbName dbClass
|
||||
.\" Start of description of a specific option. cmdName gives the
|
||||
.\" option's name as specified in the class command, dbName gives
|
||||
.\" the option's name in the option database, and dbClass gives
|
||||
.\" the option's class in the option database.
|
||||
.\"
|
||||
.\" .UL arg1 arg2
|
||||
.\" Print arg1 underlined, then print arg2 normally.
|
||||
.\"
|
||||
.\" .QW arg1 ?arg2?
|
||||
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
|
||||
.\"
|
||||
.\" .PQ arg1 ?arg2?
|
||||
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
|
||||
.\" (for trailing punctuation) and then a closing parenthesis.
|
||||
.\"
|
||||
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
|
||||
.if t .wh -1.3i ^B
|
||||
.nr ^l \n(.l
|
||||
.ad b
|
||||
.\" # Start an argument description
|
||||
.de AP
|
||||
.ie !"\\$4"" .TP \\$4
|
||||
.el \{\
|
||||
. ie !"\\$2"" .TP \\n()Cu
|
||||
. el .TP 15
|
||||
.\}
|
||||
.ta \\n()Au \\n()Bu
|
||||
.ie !"\\$3"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP (\\$3)
|
||||
.\".b
|
||||
.\}
|
||||
.el \{\
|
||||
.br
|
||||
.ie !"\\$2"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP
|
||||
.\}
|
||||
.el \{\
|
||||
\&\\fI\\$1\\fP
|
||||
.\}
|
||||
.\}
|
||||
..
|
||||
.\" # define tabbing values for .AP
|
||||
.de AS
|
||||
.nr )A 10n
|
||||
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
|
||||
.nr )B \\n()Au+15n
|
||||
.\"
|
||||
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
|
||||
.nr )C \\n()Bu+\\w'(in/out)'u+2n
|
||||
..
|
||||
.AS Tcl_Interp Tcl_CreateInterp in/out
|
||||
.\" # BS - start boxed text
|
||||
.\" # ^y = starting y location
|
||||
.\" # ^b = 1
|
||||
.de BS
|
||||
.br
|
||||
.mk ^y
|
||||
.nr ^b 1u
|
||||
.if n .nf
|
||||
.if n .ti 0
|
||||
.if n \l'\\n(.lu\(ul'
|
||||
.if n .fi
|
||||
..
|
||||
.\" # BE - end boxed text (draw box now)
|
||||
.de BE
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
.ie n \l'\\n(^lu\(ul'
|
||||
.el \{\
|
||||
.\" Draw four-sided box normally, but don't draw top of
|
||||
.\" box if the box started on an earlier page.
|
||||
.ie !\\n(^b-1 \{\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.el \}\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.\}
|
||||
.fi
|
||||
.br
|
||||
.nr ^b 0
|
||||
..
|
||||
.\" # VS - start vertical sidebar
|
||||
.\" # ^Y = starting y location
|
||||
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
|
||||
.de VS
|
||||
.if !"\\$2"" .br
|
||||
.mk ^Y
|
||||
.ie n 'mc \s12\(br\s0
|
||||
.el .nr ^v 1u
|
||||
..
|
||||
.\" # VE - end of vertical sidebar
|
||||
.de VE
|
||||
.ie n 'mc
|
||||
.el \{\
|
||||
.ev 2
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
|
||||
.sp -1
|
||||
.fi
|
||||
.ev
|
||||
.\}
|
||||
.nr ^v 0
|
||||
..
|
||||
.\" # Special macro to handle page bottom: finish off current
|
||||
.\" # box/sidebar if in box/sidebar mode, then invoked standard
|
||||
.\" # page bottom macro.
|
||||
.de ^B
|
||||
.ev 2
|
||||
'ti 0
|
||||
'nf
|
||||
.mk ^t
|
||||
.if \\n(^b \{\
|
||||
.\" Draw three-sided box if this is the box's first page,
|
||||
.\" draw two sides but no top otherwise.
|
||||
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.nr ^x \\n(^tu+1v-\\n(^Yu
|
||||
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
|
||||
.\}
|
||||
.bp
|
||||
'fi
|
||||
.ev
|
||||
.if \\n(^b \{\
|
||||
.mk ^y
|
||||
.nr ^b 2
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.mk ^Y
|
||||
.\}
|
||||
..
|
||||
.\" # DS - begin display
|
||||
.de DS
|
||||
.RS
|
||||
.nf
|
||||
.sp
|
||||
..
|
||||
.\" # DE - end display
|
||||
.de DE
|
||||
.fi
|
||||
.RE
|
||||
.sp
|
||||
..
|
||||
.\" # SO - start of list of standard options
|
||||
.de SO
|
||||
'ie '\\$1'' .ds So \\fBoptions\\fR
|
||||
'el .ds So \\fB\\$1\\fR
|
||||
.SH "STANDARD OPTIONS"
|
||||
.LP
|
||||
.nf
|
||||
.ta 5.5c 11c
|
||||
.ft B
|
||||
..
|
||||
.\" # SE - end of list of standard options
|
||||
.de SE
|
||||
.fi
|
||||
.ft R
|
||||
.LP
|
||||
See the \\*(So manual entry for details on the standard options.
|
||||
..
|
||||
.\" # OP - start of full description for a single option
|
||||
.de OP
|
||||
.LP
|
||||
.nf
|
||||
.ta 4c
|
||||
Command-Line Name: \\fB\\$1\\fR
|
||||
Database Name: \\fB\\$2\\fR
|
||||
Database Class: \\fB\\$3\\fR
|
||||
.fi
|
||||
.IP
|
||||
..
|
||||
.\" # CS - begin code excerpt
|
||||
.de CS
|
||||
.RS
|
||||
.nf
|
||||
.ta .25i .5i .75i 1i
|
||||
..
|
||||
.\" # CE - end code excerpt
|
||||
.de CE
|
||||
.fi
|
||||
.RE
|
||||
..
|
||||
.\" # UL - underline word
|
||||
.de UL
|
||||
\\$1\l'|0\(ul'\\$2
|
||||
..
|
||||
.\" # QW - apply quotation marks to word
|
||||
.de QW
|
||||
.ie '\\*(lq'"' ``\\$1''\\$2
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\$2
|
||||
..
|
||||
.\" # PQ - apply parens and quotation marks to word
|
||||
.de PQ
|
||||
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
|
||||
..
|
||||
.\" # QR - quoted range
|
||||
.de QR
|
||||
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
|
||||
..
|
||||
.\" # MT - "empty" string
|
||||
.de MT
|
||||
.QW ""
|
||||
..
|
||||
.BS
|
||||
.SH NAME
|
||||
tpool \- Part of the Tcl threading extension implementing pools of worker threads\&.
|
||||
.SH SYNOPSIS
|
||||
package require \fBTcl 8\&.4\fR
|
||||
.sp
|
||||
package require \fBThread ?2\&.8?\fR
|
||||
.sp
|
||||
\fBtpool::create\fR ?options?
|
||||
.sp
|
||||
\fBtpool::names\fR
|
||||
.sp
|
||||
\fBtpool::post\fR ?-detached? ?-nowait? \fItpool\fR \fIscript\fR
|
||||
.sp
|
||||
\fBtpool::wait\fR \fItpool\fR \fIjoblist\fR ?varname?
|
||||
.sp
|
||||
\fBtpool::cancel\fR \fItpool\fR \fIjoblist\fR ?varname?
|
||||
.sp
|
||||
\fBtpool::get\fR \fItpool\fR \fIjob\fR
|
||||
.sp
|
||||
\fBtpool::preserve\fR \fItpool\fR
|
||||
.sp
|
||||
\fBtpool::release\fR \fItpool\fR
|
||||
.sp
|
||||
\fBtpool::suspend\fR \fItpool\fR
|
||||
.sp
|
||||
\fBtpool::resume\fR \fItpool\fR
|
||||
.sp
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
This package creates and manages pools of worker threads\&. It allows you
|
||||
to post jobs to worker threads and wait for their completion\&. The
|
||||
threadpool implementation is Tcl event-loop aware\&. That means that any
|
||||
time a caller is forced to wait for an event (job being completed or
|
||||
a worker thread becoming idle or initialized), the implementation will
|
||||
enter the event loop and allow for servicing of other pending file or
|
||||
timer (or any other supported) events\&.
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
\fBtpool::create\fR ?options?
|
||||
This command creates new threadpool\&. It accepts several options as
|
||||
key-value pairs\&. Options are used to tune some threadpool parameters\&.
|
||||
The command returns the ID of the newly created threadpool\&.
|
||||
.sp
|
||||
Following options are supported:
|
||||
.RS
|
||||
.TP
|
||||
\fB-minworkers\fR \fInumber\fR
|
||||
Minimum number of worker threads needed for this threadpool instance\&.
|
||||
During threadpool creation, the implementation will create somany
|
||||
worker threads upfront and will keep at least number of them alive
|
||||
during the lifetime of the threadpool instance\&.
|
||||
Default value of this parameter is 0 (zero)\&. which means that a newly
|
||||
threadpool will have no worker threads initialy\&. All worker threads
|
||||
will be started on demand by callers running \fBtpool::post\fR command
|
||||
and posting jobs to the job queue\&.
|
||||
.TP
|
||||
\fB-maxworkers\fR \fInumber\fR
|
||||
Maximum number of worker threads allowed for this threadpool instance\&.
|
||||
If a new job is pending and there are no idle worker threads available,
|
||||
the implementation will try to create new worker thread\&. If the number
|
||||
of available worker threads is lower than the given number,
|
||||
new worker thread will start\&. The caller will automatically enter the
|
||||
event loop and wait until the worker thread has initialized\&. If\&. however,
|
||||
the number of available worker threads is equal to the given number,
|
||||
the caller will enter the event loop and wait for the first worker thread
|
||||
to get idle, thus ready to run the job\&.
|
||||
Default value of this parameter is 4 (four), which means that the
|
||||
threadpool instance will allow maximum of 4 worker threads running jobs
|
||||
or being idle waiting for new jobs to get posted to the job queue\&.
|
||||
.TP
|
||||
\fB-idletime\fR \fIseconds\fR
|
||||
Time in seconds an idle worker thread waits for the job to get posted
|
||||
to the job queue\&. If no job arrives during this interval and the time
|
||||
expires, the worker thread will check the number of currently available
|
||||
worker threads and if the number is higher than the number set by the
|
||||
\fBminthreads\fR option, it will exit\&.
|
||||
If an \fBexitscript\fR has been defined, the exiting worker thread
|
||||
will first run the script and then exit\&. Errors from the exit script,
|
||||
if any, are ignored\&.
|
||||
.sp
|
||||
The idle worker thread is not servicing the event loop\&. If you, however,
|
||||
put the worker thread into the event loop, by evaluating the
|
||||
\fBvwait\fR or other related Tcl commands, the worker thread
|
||||
will not be in the idle state, hence the idle timer will not be
|
||||
taken into account\&.
|
||||
Default value for this option is unspecified\&.
|
||||
.TP
|
||||
\fB-initcmd\fR \fIscript\fR
|
||||
Sets a Tcl script used to initialize new worker thread\&. This is usually
|
||||
used to load packages and commands in the worker, set default variables,
|
||||
create namespaces, and such\&. If the passed script runs into a Tcl error,
|
||||
the worker will not be created and the initiating command (either the
|
||||
\fBtpool::create\fR or \fBtpool::post\fR) will throw error\&.
|
||||
Default value for this option is unspecified, hence, the Tcl interpreter of
|
||||
the worker thread will contain just the initial set of Tcl commands\&.
|
||||
.TP
|
||||
\fB-exitcmd\fR \fIscript\fR
|
||||
Sets a Tcl script run when the idle worker thread exits\&. This is normaly
|
||||
used to cleanup the state of the worker thread, release reserved resources,
|
||||
cleanup memory and such\&.
|
||||
Default value for this option is unspecified, thus no Tcl script will run
|
||||
on the worker thread exit\&.
|
||||
.RE
|
||||
.sp
|
||||
.TP
|
||||
\fBtpool::names\fR
|
||||
This command returns a list of IDs of threadpools created with the
|
||||
\fBtpool::create\fR command\&. If no threadpools were found, the
|
||||
command will return empty list\&.
|
||||
.TP
|
||||
\fBtpool::post\fR ?-detached? ?-nowait? \fItpool\fR \fIscript\fR
|
||||
This command sends a \fIscript\fR to the target \fItpool\fR threadpool
|
||||
for execution\&. The script will be executed in the first available idle
|
||||
worker thread\&. If there are no idle worker threads available, the command
|
||||
will create new one, enter the event loop and service events until the
|
||||
newly created thread is initialized\&. If the current number of worker
|
||||
threads is equal to the maximum number of worker threads, as defined
|
||||
during the threadpool creation, the command will enter the event loop and
|
||||
service events while waiting for one of the worker threads to become idle\&.
|
||||
If the optional ?-nowait? argument is given, the command will not wait
|
||||
for one idle worker\&. It will just place the job in the pool's job queue
|
||||
and return immediately\&.
|
||||
.sp
|
||||
The command returns the ID of the posted job\&. This ID is used for subsequent
|
||||
\fBtpool::wait\fR, \fBtpool::get\fR and \fBtpool::cancel\fR commands to wait
|
||||
for and retrieve result of the posted script, or cancel the posted job
|
||||
respectively\&. If the optional ?-detached? argument is specified, the
|
||||
command will post a detached job\&. A detached job can not be cancelled or
|
||||
waited upon and is not identified by the job ID\&.
|
||||
.sp
|
||||
If the threadpool \fItpool\fR is not found in the list of active
|
||||
thread pools, the command will throw error\&. The error will also be triggered
|
||||
if the newly created worker thread fails to initialize\&.
|
||||
.TP
|
||||
\fBtpool::wait\fR \fItpool\fR \fIjoblist\fR ?varname?
|
||||
This command waits for one or many jobs, whose job IDs are given in the
|
||||
\fIjoblist\fR to get processed by the worker thread(s)\&. If none of the
|
||||
specified jobs are ready, the command will enter the event loop, service
|
||||
events and wait for the first job to get ready\&.
|
||||
.sp
|
||||
The command returns the list of completed job IDs\&. If the optional variable
|
||||
?varname? is given, it will be set to the list of jobs in the
|
||||
\fIjoblist\fR which are still pending\&. If the threadpool \fItpool\fR
|
||||
is not found in the list of active thread pools, the command will throw error\&.
|
||||
.TP
|
||||
\fBtpool::cancel\fR \fItpool\fR \fIjoblist\fR ?varname?
|
||||
This command cancels the previously posted jobs given by the \fIjoblist\fR
|
||||
to the pool \fItpool\fR\&. Job cancellation succeeds only for job still
|
||||
waiting to be processed\&. If the job is already being executed by one of
|
||||
the worker threads, the job will not be cancelled\&.
|
||||
The command returns the list of cancelled job IDs\&. If the optional variable
|
||||
?varname? is given, it will be set to the list of jobs in the
|
||||
\fIjoblist\fR which were not cancelled\&. If the threadpool \fItpool\fR
|
||||
is not found in the list of active thread pools, the command will throw error\&.
|
||||
.TP
|
||||
\fBtpool::get\fR \fItpool\fR \fIjob\fR
|
||||
This command retrieves the result of the previously posted \fIjob\fR\&.
|
||||
Only results of jobs waited upon with the \fBtpool::wait\fR command
|
||||
can be retrieved\&. If the execution of the script resulted in error,
|
||||
the command will throw the error and update the \fBerrorInfo\fR and
|
||||
\fBerrorCode\fR variables correspondingly\&. If the pool \fItpool\fR
|
||||
is not found in the list of threadpools, the command will throw error\&.
|
||||
If the job \fIjob\fR is not ready for retrieval, because it is currently
|
||||
being executed by the worker thread, the command will throw error\&.
|
||||
.TP
|
||||
\fBtpool::preserve\fR \fItpool\fR
|
||||
Each call to this command increments the reference counter of the
|
||||
threadpool \fItpool\fR by one (1)\&. Command returns the value of the
|
||||
reference counter after the increment\&.
|
||||
By incrementing the reference counter, the caller signalizes that
|
||||
he/she wishes to use the resource for a longer period of time\&.
|
||||
.TP
|
||||
\fBtpool::release\fR \fItpool\fR
|
||||
Each call to this command decrements the reference counter of the
|
||||
threadpool \fItpool\fR by one (1)\&.Command returns the value of the
|
||||
reference counter after the decrement\&.
|
||||
When the reference counter reaches zero (0), the threadpool \fItpool\fR
|
||||
is marked for termination\&. You should not reference the threadpool
|
||||
after the \fBtpool::release\fR command returns zero\&. The \fItpool\fR
|
||||
handle goes out of scope and should not be used any more\&. Any following
|
||||
reference to the same threadpool handle will result in Tcl error\&.
|
||||
.TP
|
||||
\fBtpool::suspend\fR \fItpool\fR
|
||||
Suspends processing work on this queue\&. All pool workers are paused
|
||||
but additional work can be added to the pool\&. Note that adding the
|
||||
additional work will not increase the number of workers dynamically
|
||||
as the pool processing is suspended\&. Number of workers is maintained
|
||||
to the count that was found prior suspending worker activity\&.
|
||||
If you need to assure certain number of worker threads, use the
|
||||
\fBminworkers\fR option of the \fBtpool::create\fR command\&.
|
||||
.TP
|
||||
\fBtpool::resume\fR \fItpool\fR
|
||||
Resume processing work on this queue\&. All paused (suspended)
|
||||
workers are free to get work from the pool\&. Note that resuming pool
|
||||
operation will just let already created workers to proceed\&.
|
||||
It will not create additional worker threads to handle the work
|
||||
posted to the pool's work queue\&.
|
||||
.PP
|
||||
.SH DISCUSSION
|
||||
Threadpool is one of the most common threading paradigm when it comes
|
||||
to server applications handling a large number of relatively small tasks\&.
|
||||
A very simplistic model for building a server application would be to
|
||||
create a new thread each time a request arrives and service the request
|
||||
in the new thread\&. One of the disadvantages of this approach is that
|
||||
the overhead of creating a new thread for each request is significant;
|
||||
a server that created a new thread for each request would spend more time
|
||||
and consume more system resources in creating and destroying threads than
|
||||
in processing actual user requests\&. In addition to the overhead of
|
||||
creating and destroying threads, active threads consume system resources\&.
|
||||
Creating too many threads can cause the system to run out of memory or
|
||||
trash due to excessive memory consumption\&.
|
||||
.PP
|
||||
A thread pool offers a solution to both the problem of thread life-cycle
|
||||
overhead and the problem of resource trashing\&. By reusing threads for
|
||||
multiple tasks, the thread-creation overhead is spread over many tasks\&.
|
||||
As a bonus, because the thread already exists when a request arrives,
|
||||
the delay introduced by thread creation is eliminated\&. Thus, the request
|
||||
can be serviced immediately\&. Furthermore, by properly tuning the number
|
||||
of threads in the thread pool, resource thrashing may also be eliminated
|
||||
by forcing any request to wait until a thread is available to process it\&.
|
||||
.SH "SEE ALSO"
|
||||
thread, tsv, ttrace
|
||||
.SH KEYWORDS
|
||||
thread, threadpool
|
||||
628
pkgs/thread2.8.7/doc/man/tsv.n
Normal file
628
pkgs/thread2.8.7/doc/man/tsv.n
Normal file
@@ -0,0 +1,628 @@
|
||||
'\"
|
||||
'\" Generated from file '' by tcllib/doctools with format 'nroff'
|
||||
'\"
|
||||
.TH "tsv" n 2\&.8 "Tcl Threading"
|
||||
.\" The -*- nroff -*- definitions below are for supplemental macros used
|
||||
.\" in Tcl/Tk manual entries.
|
||||
.\"
|
||||
.\" .AP type name in/out ?indent?
|
||||
.\" Start paragraph describing an argument to a library procedure.
|
||||
.\" type is type of argument (int, etc.), in/out is either "in", "out",
|
||||
.\" or "in/out" to describe whether procedure reads or modifies arg,
|
||||
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
|
||||
.\" needed; use .AS below instead)
|
||||
.\"
|
||||
.\" .AS ?type? ?name?
|
||||
.\" Give maximum sizes of arguments for setting tab stops. Type and
|
||||
.\" name are examples of largest possible arguments that will be passed
|
||||
.\" to .AP later. If args are omitted, default tab stops are used.
|
||||
.\"
|
||||
.\" .BS
|
||||
.\" Start box enclosure. From here until next .BE, everything will be
|
||||
.\" enclosed in one large box.
|
||||
.\"
|
||||
.\" .BE
|
||||
.\" End of box enclosure.
|
||||
.\"
|
||||
.\" .CS
|
||||
.\" Begin code excerpt.
|
||||
.\"
|
||||
.\" .CE
|
||||
.\" End code excerpt.
|
||||
.\"
|
||||
.\" .VS ?version? ?br?
|
||||
.\" Begin vertical sidebar, for use in marking newly-changed parts
|
||||
.\" of man pages. The first argument is ignored and used for recording
|
||||
.\" the version when the .VS was added, so that the sidebars can be
|
||||
.\" found and removed when they reach a certain age. If another argument
|
||||
.\" is present, then a line break is forced before starting the sidebar.
|
||||
.\"
|
||||
.\" .VE
|
||||
.\" End of vertical sidebar.
|
||||
.\"
|
||||
.\" .DS
|
||||
.\" Begin an indented unfilled display.
|
||||
.\"
|
||||
.\" .DE
|
||||
.\" End of indented unfilled display.
|
||||
.\"
|
||||
.\" .SO ?manpage?
|
||||
.\" Start of list of standard options for a Tk widget. The manpage
|
||||
.\" argument defines where to look up the standard options; if
|
||||
.\" omitted, defaults to "options". The options follow on successive
|
||||
.\" lines, in three columns separated by tabs.
|
||||
.\"
|
||||
.\" .SE
|
||||
.\" End of list of standard options for a Tk widget.
|
||||
.\"
|
||||
.\" .OP cmdName dbName dbClass
|
||||
.\" Start of description of a specific option. cmdName gives the
|
||||
.\" option's name as specified in the class command, dbName gives
|
||||
.\" the option's name in the option database, and dbClass gives
|
||||
.\" the option's class in the option database.
|
||||
.\"
|
||||
.\" .UL arg1 arg2
|
||||
.\" Print arg1 underlined, then print arg2 normally.
|
||||
.\"
|
||||
.\" .QW arg1 ?arg2?
|
||||
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
|
||||
.\"
|
||||
.\" .PQ arg1 ?arg2?
|
||||
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
|
||||
.\" (for trailing punctuation) and then a closing parenthesis.
|
||||
.\"
|
||||
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
|
||||
.if t .wh -1.3i ^B
|
||||
.nr ^l \n(.l
|
||||
.ad b
|
||||
.\" # Start an argument description
|
||||
.de AP
|
||||
.ie !"\\$4"" .TP \\$4
|
||||
.el \{\
|
||||
. ie !"\\$2"" .TP \\n()Cu
|
||||
. el .TP 15
|
||||
.\}
|
||||
.ta \\n()Au \\n()Bu
|
||||
.ie !"\\$3"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP (\\$3)
|
||||
.\".b
|
||||
.\}
|
||||
.el \{\
|
||||
.br
|
||||
.ie !"\\$2"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP
|
||||
.\}
|
||||
.el \{\
|
||||
\&\\fI\\$1\\fP
|
||||
.\}
|
||||
.\}
|
||||
..
|
||||
.\" # define tabbing values for .AP
|
||||
.de AS
|
||||
.nr )A 10n
|
||||
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
|
||||
.nr )B \\n()Au+15n
|
||||
.\"
|
||||
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
|
||||
.nr )C \\n()Bu+\\w'(in/out)'u+2n
|
||||
..
|
||||
.AS Tcl_Interp Tcl_CreateInterp in/out
|
||||
.\" # BS - start boxed text
|
||||
.\" # ^y = starting y location
|
||||
.\" # ^b = 1
|
||||
.de BS
|
||||
.br
|
||||
.mk ^y
|
||||
.nr ^b 1u
|
||||
.if n .nf
|
||||
.if n .ti 0
|
||||
.if n \l'\\n(.lu\(ul'
|
||||
.if n .fi
|
||||
..
|
||||
.\" # BE - end boxed text (draw box now)
|
||||
.de BE
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
.ie n \l'\\n(^lu\(ul'
|
||||
.el \{\
|
||||
.\" Draw four-sided box normally, but don't draw top of
|
||||
.\" box if the box started on an earlier page.
|
||||
.ie !\\n(^b-1 \{\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.el \}\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.\}
|
||||
.fi
|
||||
.br
|
||||
.nr ^b 0
|
||||
..
|
||||
.\" # VS - start vertical sidebar
|
||||
.\" # ^Y = starting y location
|
||||
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
|
||||
.de VS
|
||||
.if !"\\$2"" .br
|
||||
.mk ^Y
|
||||
.ie n 'mc \s12\(br\s0
|
||||
.el .nr ^v 1u
|
||||
..
|
||||
.\" # VE - end of vertical sidebar
|
||||
.de VE
|
||||
.ie n 'mc
|
||||
.el \{\
|
||||
.ev 2
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
|
||||
.sp -1
|
||||
.fi
|
||||
.ev
|
||||
.\}
|
||||
.nr ^v 0
|
||||
..
|
||||
.\" # Special macro to handle page bottom: finish off current
|
||||
.\" # box/sidebar if in box/sidebar mode, then invoked standard
|
||||
.\" # page bottom macro.
|
||||
.de ^B
|
||||
.ev 2
|
||||
'ti 0
|
||||
'nf
|
||||
.mk ^t
|
||||
.if \\n(^b \{\
|
||||
.\" Draw three-sided box if this is the box's first page,
|
||||
.\" draw two sides but no top otherwise.
|
||||
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.nr ^x \\n(^tu+1v-\\n(^Yu
|
||||
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
|
||||
.\}
|
||||
.bp
|
||||
'fi
|
||||
.ev
|
||||
.if \\n(^b \{\
|
||||
.mk ^y
|
||||
.nr ^b 2
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.mk ^Y
|
||||
.\}
|
||||
..
|
||||
.\" # DS - begin display
|
||||
.de DS
|
||||
.RS
|
||||
.nf
|
||||
.sp
|
||||
..
|
||||
.\" # DE - end display
|
||||
.de DE
|
||||
.fi
|
||||
.RE
|
||||
.sp
|
||||
..
|
||||
.\" # SO - start of list of standard options
|
||||
.de SO
|
||||
'ie '\\$1'' .ds So \\fBoptions\\fR
|
||||
'el .ds So \\fB\\$1\\fR
|
||||
.SH "STANDARD OPTIONS"
|
||||
.LP
|
||||
.nf
|
||||
.ta 5.5c 11c
|
||||
.ft B
|
||||
..
|
||||
.\" # SE - end of list of standard options
|
||||
.de SE
|
||||
.fi
|
||||
.ft R
|
||||
.LP
|
||||
See the \\*(So manual entry for details on the standard options.
|
||||
..
|
||||
.\" # OP - start of full description for a single option
|
||||
.de OP
|
||||
.LP
|
||||
.nf
|
||||
.ta 4c
|
||||
Command-Line Name: \\fB\\$1\\fR
|
||||
Database Name: \\fB\\$2\\fR
|
||||
Database Class: \\fB\\$3\\fR
|
||||
.fi
|
||||
.IP
|
||||
..
|
||||
.\" # CS - begin code excerpt
|
||||
.de CS
|
||||
.RS
|
||||
.nf
|
||||
.ta .25i .5i .75i 1i
|
||||
..
|
||||
.\" # CE - end code excerpt
|
||||
.de CE
|
||||
.fi
|
||||
.RE
|
||||
..
|
||||
.\" # UL - underline word
|
||||
.de UL
|
||||
\\$1\l'|0\(ul'\\$2
|
||||
..
|
||||
.\" # QW - apply quotation marks to word
|
||||
.de QW
|
||||
.ie '\\*(lq'"' ``\\$1''\\$2
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\$2
|
||||
..
|
||||
.\" # PQ - apply parens and quotation marks to word
|
||||
.de PQ
|
||||
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
|
||||
..
|
||||
.\" # QR - quoted range
|
||||
.de QR
|
||||
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
|
||||
..
|
||||
.\" # MT - "empty" string
|
||||
.de MT
|
||||
.QW ""
|
||||
..
|
||||
.BS
|
||||
.SH NAME
|
||||
tsv \- Part of the Tcl threading extension allowing script level manipulation of data shared between threads\&.
|
||||
.SH SYNOPSIS
|
||||
package require \fBTcl 8\&.4\fR
|
||||
.sp
|
||||
package require \fBThread ?2\&.8?\fR
|
||||
.sp
|
||||
\fBtsv::names\fR ?pattern?
|
||||
.sp
|
||||
\fBtsv::object\fR \fIvarname\fR \fIelement\fR
|
||||
.sp
|
||||
\fBtsv::set\fR \fIvarname\fR \fIelement\fR ?value?
|
||||
.sp
|
||||
\fBtsv::get\fR \fIvarname\fR \fIelement\fR ?namedvar?
|
||||
.sp
|
||||
\fBtsv::unset\fR \fIvarname\fR ?element?
|
||||
.sp
|
||||
\fBtsv::exists\fR \fIvarname\fR \fIelement\fR
|
||||
.sp
|
||||
\fBtsv::pop\fR \fIvarname\fR \fIelement\fR
|
||||
.sp
|
||||
\fBtsv::move\fR \fIvarname\fR \fIoldname\fR \fInewname\fR
|
||||
.sp
|
||||
\fBtsv::incr\fR \fIvarname\fR \fIelement\fR ?count?
|
||||
.sp
|
||||
\fBtsv::append\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
.sp
|
||||
\fBtsv::lock\fR \fIvarname\fR \fIarg\fR ?arg \&.\&.\&.?
|
||||
.sp
|
||||
\fBtsv::handlers\fR
|
||||
.sp
|
||||
\fBtsv::lappend\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
.sp
|
||||
\fBtsv::linsert\fR \fIvarname\fR \fIelement\fR \fIindex\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
.sp
|
||||
\fBtsv::lreplace\fR \fIvarname\fR \fIelement\fR \fIfirst\fR \fIlast\fR ?value \&.\&.\&.?
|
||||
.sp
|
||||
\fBtsv::llength\fR \fIvarname\fR \fIelement\fR
|
||||
.sp
|
||||
\fBtsv::lindex\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
.sp
|
||||
\fBtsv::lrange\fR \fIvarname\fR \fIelement\fR \fIfrom\fR \fIto\fR
|
||||
.sp
|
||||
\fBtsv::lsearch\fR \fIvarname\fR \fIelement\fR ?options? \fIpattern\fR
|
||||
.sp
|
||||
\fBtsv::lset\fR \fIvarname\fR \fIelement\fR \fIindex\fR ?index \&.\&.\&.? \fIvalue\fR
|
||||
.sp
|
||||
\fBtsv::lpop\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
.sp
|
||||
\fBtsv::lpush\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
.sp
|
||||
\fBtsv::array set\fR \fIvarname\fR \fIlist\fR
|
||||
.sp
|
||||
\fBtsv::array get\fR \fIvarname\fR ?pattern?
|
||||
.sp
|
||||
\fBtsv::array names\fR \fIvarname\fR ?pattern?
|
||||
.sp
|
||||
\fBtsv::array size\fR \fIvarname\fR
|
||||
.sp
|
||||
\fBtsv::array reset\fR \fIvarname\fR \fIlist\fR
|
||||
.sp
|
||||
\fBtsv::array bind\fR \fIvarname\fR \fIhandle\fR
|
||||
.sp
|
||||
\fBtsv::array unbind\fR \fIvarname\fR
|
||||
.sp
|
||||
\fBtsv::array isbound\fR \fIvarname\fR
|
||||
.sp
|
||||
\fBtsv::keyldel\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR
|
||||
.sp
|
||||
\fBtsv::keylget\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR ?retvar?
|
||||
.sp
|
||||
\fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key?
|
||||
.sp
|
||||
\fBtsv::keylset\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR \fIvalue\fR ?key value\&.\&.?
|
||||
.sp
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
This section describes commands implementing thread shared variables\&.
|
||||
A thread shared variable is very similar to a Tcl array but in
|
||||
contrast to a Tcl array it is created in shared memory and can
|
||||
be accessed from many threads at the same time\&. Important feature of
|
||||
thread shared variable is that each access to the variable is internaly
|
||||
protected by a mutex so script programmer does not have to take care
|
||||
about locking the variable himself\&.
|
||||
.PP
|
||||
Thread shared variables are not bound to any thread explicitly\&. That
|
||||
means that when a thread which created any of thread shared variables
|
||||
exits, the variable and associated memory is not unset/reclaimed\&.
|
||||
User has to explicitly unset the variable to reclaim the memory
|
||||
consumed by the variable\&.
|
||||
.SH "ELEMENT COMMANDS"
|
||||
.TP
|
||||
\fBtsv::names\fR ?pattern?
|
||||
Returns names of shared variables matching optional ?pattern?
|
||||
or all known variables if pattern is ommited\&.
|
||||
.TP
|
||||
\fBtsv::object\fR \fIvarname\fR \fIelement\fR
|
||||
Creates object accessor command for the \fIelement\fR in the
|
||||
shared variable \fIvarname\fR\&. Using this command, one can apply most
|
||||
of the other shared variable commands as method functions of
|
||||
the element object command\&. The object command is automatically
|
||||
deleted when the element which this command is pointing to is unset\&.
|
||||
.CS
|
||||
|
||||
|
||||
% tsv::set foo bar "A shared string"
|
||||
% set string [tsv::object foo bar]
|
||||
% $string append " appended"
|
||||
=> A shared string appended
|
||||
|
||||
.CE
|
||||
.TP
|
||||
\fBtsv::set\fR \fIvarname\fR \fIelement\fR ?value?
|
||||
Sets the value of the \fIelement\fR in the shared variable \fIvarname\fR
|
||||
to \fIvalue\fR and returns the value to caller\&. The \fIvalue\fR
|
||||
may be ommited, in which case the command will return the current
|
||||
value of the element\&. If the element cannot be found, error is triggered\&.
|
||||
.TP
|
||||
\fBtsv::get\fR \fIvarname\fR \fIelement\fR ?namedvar?
|
||||
Retrieves the value of the \fIelement\fR from the shared variable \fIvarname\fR\&.
|
||||
If the optional argument \fInamedvar\fR is given, the value is
|
||||
stored in the named variable\&. Return value of the command depends
|
||||
of the existence of the optional argument \fInamedvar\fR\&.
|
||||
If the argument is ommited and the requested element cannot be found
|
||||
in the shared array, the command triggers error\&. If, however, the
|
||||
optional argument is given on the command line, the command returns
|
||||
true (1) if the element is found or false (0) if the element is not found\&.
|
||||
.TP
|
||||
\fBtsv::unset\fR \fIvarname\fR ?element?
|
||||
Unsets the \fIelement\fR from the shared variable \fIvarname\fR\&.
|
||||
If the optional element is not given, it deletes the variable\&.
|
||||
.TP
|
||||
\fBtsv::exists\fR \fIvarname\fR \fIelement\fR
|
||||
Checks wether the \fIelement\fR exists in the shared variable \fIvarname\fR
|
||||
and returns true (1) if it does or false (0) if it doesn't\&.
|
||||
.TP
|
||||
\fBtsv::pop\fR \fIvarname\fR \fIelement\fR
|
||||
Returns value of the \fIelement\fR in the shared variable \fIvarname\fR
|
||||
and unsets the element, all in one atomic operation\&.
|
||||
.TP
|
||||
\fBtsv::move\fR \fIvarname\fR \fIoldname\fR \fInewname\fR
|
||||
Renames the element \fIoldname\fR to the \fInewname\fR in the
|
||||
shared variable \fIvarname\fR\&. This effectively performs an get/unset/set
|
||||
sequence of operations but all in one atomic step\&.
|
||||
.TP
|
||||
\fBtsv::incr\fR \fIvarname\fR \fIelement\fR ?count?
|
||||
Similar to standard Tcl \fBincr\fR command but increments the value
|
||||
of the \fIelement\fR in shared variaboe \fIvarname\fR instead of
|
||||
the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::append\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
Similar to standard Tcl \fBappend\fR command but appends one or more
|
||||
values to the \fIelement\fR in shared variable \fIvarname\fR instead of the
|
||||
Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lock\fR \fIvarname\fR \fIarg\fR ?arg \&.\&.\&.?
|
||||
This command concatenates passed arguments and evaluates the
|
||||
resulting script under the internal mutex protection\&. During the
|
||||
script evaluation, the entire shared variable is locked\&. For shared
|
||||
variable commands within the script, internal locking is disabled
|
||||
so no deadlock can occur\&. It is also allowed to unset the shared
|
||||
variable from within the script\&. The shared variable is automatically
|
||||
created if it did not exists at the time of the first lock operation\&.
|
||||
.CS
|
||||
|
||||
|
||||
% tsv::lock foo {
|
||||
tsv::lappend foo bar 1
|
||||
tsv::lappend foo bar 2
|
||||
puts stderr [tsv::set foo bar]
|
||||
tsv::unset foo
|
||||
}
|
||||
|
||||
.CE
|
||||
.TP
|
||||
\fBtsv::handlers\fR
|
||||
Returns the names of all persistent storage handlers enabled at compile time\&.
|
||||
See \fBARRAY COMMANDS\fR for details\&.
|
||||
.PP
|
||||
.SH "LIST COMMANDS"
|
||||
Those command are similar to the equivalently named Tcl command\&. The difference
|
||||
is that they operate on elements of shared arrays\&.
|
||||
.TP
|
||||
\fBtsv::lappend\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
Similar to standard Tcl \fBlappend\fR command but appends one
|
||||
or more values to the \fIelement\fR in shared variable \fIvarname\fR
|
||||
instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::linsert\fR \fIvarname\fR \fIelement\fR \fIindex\fR \fIvalue\fR ?value \&.\&.\&.?
|
||||
Similar to standard Tcl \fBlinsert\fR command but inserts one
|
||||
or more values at the \fIindex\fR list position in the
|
||||
\fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lreplace\fR \fIvarname\fR \fIelement\fR \fIfirst\fR \fIlast\fR ?value \&.\&.\&.?
|
||||
Similar to standard Tcl \fBlreplace\fR command but replaces one
|
||||
or more values between the \fIfirst\fR and \fIlast\fR position
|
||||
in the \fIelement\fR of the shared variable \fIvarname\fR instead of
|
||||
the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::llength\fR \fIvarname\fR \fIelement\fR
|
||||
Similar to standard Tcl \fBllength\fR command but returns length
|
||||
of the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl
|
||||
variable\&.
|
||||
.TP
|
||||
\fBtsv::lindex\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
Similar to standard Tcl \fBlindex\fR command but returns the value
|
||||
at the \fIindex\fR list position of the \fIelement\fR from
|
||||
the shared variable \fIvarname\fR instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lrange\fR \fIvarname\fR \fIelement\fR \fIfrom\fR \fIto\fR
|
||||
Similar to standard Tcl \fBlrange\fR command but returns values
|
||||
between \fIfrom\fR and \fIto\fR list positions from the
|
||||
\fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lsearch\fR \fIvarname\fR \fIelement\fR ?options? \fIpattern\fR
|
||||
Similar to standard Tcl \fBlsearch\fR command but searches the \fIelement\fR
|
||||
in the shared variable \fIvarname\fR instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lset\fR \fIvarname\fR \fIelement\fR \fIindex\fR ?index \&.\&.\&.? \fIvalue\fR
|
||||
Similar to standard Tcl \fBlset\fR command but sets the \fIelement\fR
|
||||
in the shared variable \fIvarname\fR instead of the Tcl variable\&.
|
||||
.TP
|
||||
\fBtsv::lpop\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
Similar to the standard Tcl \fBlindex\fR command but in addition to
|
||||
returning, it also splices the value out of the \fIelement\fR
|
||||
from the shared variable \fIvarname\fR in one atomic operation\&.
|
||||
In contrast to the Tcl \fBlindex\fR command, this command returns
|
||||
no value to the caller\&.
|
||||
.TP
|
||||
\fBtsv::lpush\fR \fIvarname\fR \fIelement\fR ?index?
|
||||
This command performes the opposite of the \fBtsv::lpop\fR command\&.
|
||||
As its counterpart, it returns no value to the caller\&.
|
||||
.PP
|
||||
.SH "ARRAY COMMANDS"
|
||||
This command supports most of the options of the standard Tcl
|
||||
\fBarray\fR command\&. In addition to those, it allows binding
|
||||
a shared variable to some persisten storage databases\&. Currently the persistent
|
||||
options supported are the famous GNU Gdbm and LMDB\&. These options have to be
|
||||
selected during the package compilation time\&.
|
||||
The implementation provides hooks for defining other persistency layers, if
|
||||
needed\&.
|
||||
.TP
|
||||
\fBtsv::array set\fR \fIvarname\fR \fIlist\fR
|
||||
Does the same as standard Tcl \fBarray set\fR\&.
|
||||
.TP
|
||||
\fBtsv::array get\fR \fIvarname\fR ?pattern?
|
||||
Does the same as standard Tcl \fBarray get\fR\&.
|
||||
.TP
|
||||
\fBtsv::array names\fR \fIvarname\fR ?pattern?
|
||||
Does the same as standard Tcl \fBarray names\fR\&.
|
||||
.TP
|
||||
\fBtsv::array size\fR \fIvarname\fR
|
||||
Does the same as standard Tcl \fBarray size\fR\&.
|
||||
.TP
|
||||
\fBtsv::array reset\fR \fIvarname\fR \fIlist\fR
|
||||
Does the same as standard Tcl \fBarray set\fR but it clears
|
||||
the \fIvarname\fR and sets new values from the list atomically\&.
|
||||
.TP
|
||||
\fBtsv::array bind\fR \fIvarname\fR \fIhandle\fR
|
||||
Binds the \fIvarname\fR to the persistent storage \fIhandle\fR\&.
|
||||
The format of the \fIhandle\fR is <handler>:<address>, where <handler> is
|
||||
"gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the
|
||||
database file\&.
|
||||
.TP
|
||||
\fBtsv::array unbind\fR \fIvarname\fR
|
||||
Unbinds the shared \fIarray\fR from its bound persistent storage\&.
|
||||
.TP
|
||||
\fBtsv::array isbound\fR \fIvarname\fR
|
||||
Returns true (1) if the shared \fIvarname\fR is bound to some
|
||||
persistent storage or zero (0) if not\&.
|
||||
.PP
|
||||
.SH "KEYED LIST COMMANDS"
|
||||
Keyed list commands are borrowed from the TclX package\&. Keyed lists provide
|
||||
a structured data type built upon standard Tcl lists\&. This is a functionality
|
||||
similar to structs in the C programming language\&.
|
||||
.PP
|
||||
A keyed list is a list in which each element contains a key and value
|
||||
pair\&. These element pairs are stored as lists themselves, where the key
|
||||
is the first element of the list, and the value is the second\&. The
|
||||
key-value pairs are referred to as fields\&. This is an example of a
|
||||
keyed list:
|
||||
.CS
|
||||
|
||||
|
||||
{{NAME {Frank Zappa}} {JOB {musician and composer}}}
|
||||
|
||||
.CE
|
||||
Fields may contain subfields; `\&.' is the separator character\&. Subfields
|
||||
are actually fields where the value is another keyed list\&. Thus the
|
||||
following list has the top level fields ID and NAME, and subfields
|
||||
NAME\&.FIRST and NAME\&.LAST:
|
||||
.CS
|
||||
|
||||
|
||||
{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}
|
||||
|
||||
.CE
|
||||
There is no limit to the recursive depth of subfields,
|
||||
allowing one to build complex data structures\&. Keyed lists are constructed
|
||||
and accessed via a number of commands\&. All keyed list management
|
||||
commands take the name of the variable containing the keyed list as an
|
||||
argument (i\&.e\&. passed by reference), rather than passing the list directly\&.
|
||||
.TP
|
||||
\fBtsv::keyldel\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR
|
||||
Delete the field specified by \fIkey\fR from the keyed list \fIkeylist\fR
|
||||
in the shared variable \fIvarname\fR\&.
|
||||
This removes both the key and the value from the keyed list\&.
|
||||
.TP
|
||||
\fBtsv::keylget\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR ?retvar?
|
||||
Return the value associated with \fIkey\fR from the keyed list \fIkeylist\fR
|
||||
in the shared variable \fIvarname\fR\&.
|
||||
If the optional \fIretvar\fR is not specified, then the value will be
|
||||
returned as the result of the command\&. In this case, if key is not found
|
||||
in the list, an error will result\&.
|
||||
.sp
|
||||
If \fIretvar\fR is specified and \fIkey\fR is in the list, then the value
|
||||
is returned in the variable \fIretvar\fR and the command returns 1 if the
|
||||
key was present within the list\&. If \fIkey\fR isn't in the list, the
|
||||
command will return 0, and \fIretvar\fR will be left unchanged\&. If {} is
|
||||
specified for \fIretvar\fR, the value is not returned, allowing the Tcl
|
||||
programmer to determine if a \fIkey\fR is present in a keyed list without
|
||||
setting a variable as a side-effect\&.
|
||||
.TP
|
||||
\fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key?
|
||||
Return the a list of the keys in the keyed list \fIkeylist\fR in the
|
||||
shared variable \fIvarname\fR\&. If \fIkey\fR is specified, then it is
|
||||
the name of a key field who's subfield keys are to be retrieved\&.
|
||||
.TP
|
||||
\fBtsv::keylset\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR \fIvalue\fR ?key value\&.\&.?
|
||||
Set the value associated with \fIkey\fR, in the keyed list \fIkeylist\fR
|
||||
to \fIvalue\fR\&. If the \fIkeylist\fR does not exists, it is created\&.
|
||||
If \fIkey\fR is not currently in the list, it will be added\&. If it already
|
||||
exists, \fIvalue\fR replaces the existing value\&. Multiple keywords and
|
||||
values may be specified, if desired\&.
|
||||
.PP
|
||||
.SH DISCUSSION
|
||||
The current implementation of thread shared variables allows for easy and
|
||||
convenient access to data shared between different threads\&.
|
||||
Internally, the data is stored in Tcl objects and all package commands
|
||||
operate on internal data representation, thus minimizing shimmering and
|
||||
improving performance\&. Special care has been taken to assure that all
|
||||
object data is properly locked and deep-copied when moving objects between
|
||||
threads\&.
|
||||
.PP
|
||||
Due to the internal design of the Tcl core, there is no provision of full
|
||||
integration of shared variables within the Tcl syntax, unfortunately\&. All
|
||||
access to shared data must be performed with the supplied package commands\&.
|
||||
Also, variable traces are not supported\&. But even so, benefits of easy,
|
||||
simple and safe shared data manipulation outweights imposed limitations\&.
|
||||
.SH CREDITS
|
||||
Thread shared variables are inspired by the nsv interface found in
|
||||
AOLserver, a highly scalable Web server from America Online\&.
|
||||
.SH "SEE ALSO"
|
||||
thread, tpool, ttrace
|
||||
.SH KEYWORDS
|
||||
locking, synchronization, thread shared data, threads
|
||||
506
pkgs/thread2.8.7/doc/man/ttrace.n
Normal file
506
pkgs/thread2.8.7/doc/man/ttrace.n
Normal file
@@ -0,0 +1,506 @@
|
||||
'\"
|
||||
'\" Generated from file '' by tcllib/doctools with format 'nroff'
|
||||
'\"
|
||||
.TH "ttrace" n 2\&.8 "Tcl Threading"
|
||||
.\" The -*- nroff -*- definitions below are for supplemental macros used
|
||||
.\" in Tcl/Tk manual entries.
|
||||
.\"
|
||||
.\" .AP type name in/out ?indent?
|
||||
.\" Start paragraph describing an argument to a library procedure.
|
||||
.\" type is type of argument (int, etc.), in/out is either "in", "out",
|
||||
.\" or "in/out" to describe whether procedure reads or modifies arg,
|
||||
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
|
||||
.\" needed; use .AS below instead)
|
||||
.\"
|
||||
.\" .AS ?type? ?name?
|
||||
.\" Give maximum sizes of arguments for setting tab stops. Type and
|
||||
.\" name are examples of largest possible arguments that will be passed
|
||||
.\" to .AP later. If args are omitted, default tab stops are used.
|
||||
.\"
|
||||
.\" .BS
|
||||
.\" Start box enclosure. From here until next .BE, everything will be
|
||||
.\" enclosed in one large box.
|
||||
.\"
|
||||
.\" .BE
|
||||
.\" End of box enclosure.
|
||||
.\"
|
||||
.\" .CS
|
||||
.\" Begin code excerpt.
|
||||
.\"
|
||||
.\" .CE
|
||||
.\" End code excerpt.
|
||||
.\"
|
||||
.\" .VS ?version? ?br?
|
||||
.\" Begin vertical sidebar, for use in marking newly-changed parts
|
||||
.\" of man pages. The first argument is ignored and used for recording
|
||||
.\" the version when the .VS was added, so that the sidebars can be
|
||||
.\" found and removed when they reach a certain age. If another argument
|
||||
.\" is present, then a line break is forced before starting the sidebar.
|
||||
.\"
|
||||
.\" .VE
|
||||
.\" End of vertical sidebar.
|
||||
.\"
|
||||
.\" .DS
|
||||
.\" Begin an indented unfilled display.
|
||||
.\"
|
||||
.\" .DE
|
||||
.\" End of indented unfilled display.
|
||||
.\"
|
||||
.\" .SO ?manpage?
|
||||
.\" Start of list of standard options for a Tk widget. The manpage
|
||||
.\" argument defines where to look up the standard options; if
|
||||
.\" omitted, defaults to "options". The options follow on successive
|
||||
.\" lines, in three columns separated by tabs.
|
||||
.\"
|
||||
.\" .SE
|
||||
.\" End of list of standard options for a Tk widget.
|
||||
.\"
|
||||
.\" .OP cmdName dbName dbClass
|
||||
.\" Start of description of a specific option. cmdName gives the
|
||||
.\" option's name as specified in the class command, dbName gives
|
||||
.\" the option's name in the option database, and dbClass gives
|
||||
.\" the option's class in the option database.
|
||||
.\"
|
||||
.\" .UL arg1 arg2
|
||||
.\" Print arg1 underlined, then print arg2 normally.
|
||||
.\"
|
||||
.\" .QW arg1 ?arg2?
|
||||
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
|
||||
.\"
|
||||
.\" .PQ arg1 ?arg2?
|
||||
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
|
||||
.\" (for trailing punctuation) and then a closing parenthesis.
|
||||
.\"
|
||||
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
|
||||
.if t .wh -1.3i ^B
|
||||
.nr ^l \n(.l
|
||||
.ad b
|
||||
.\" # Start an argument description
|
||||
.de AP
|
||||
.ie !"\\$4"" .TP \\$4
|
||||
.el \{\
|
||||
. ie !"\\$2"" .TP \\n()Cu
|
||||
. el .TP 15
|
||||
.\}
|
||||
.ta \\n()Au \\n()Bu
|
||||
.ie !"\\$3"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP (\\$3)
|
||||
.\".b
|
||||
.\}
|
||||
.el \{\
|
||||
.br
|
||||
.ie !"\\$2"" \{\
|
||||
\&\\$1 \\fI\\$2\\fP
|
||||
.\}
|
||||
.el \{\
|
||||
\&\\fI\\$1\\fP
|
||||
.\}
|
||||
.\}
|
||||
..
|
||||
.\" # define tabbing values for .AP
|
||||
.de AS
|
||||
.nr )A 10n
|
||||
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
|
||||
.nr )B \\n()Au+15n
|
||||
.\"
|
||||
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
|
||||
.nr )C \\n()Bu+\\w'(in/out)'u+2n
|
||||
..
|
||||
.AS Tcl_Interp Tcl_CreateInterp in/out
|
||||
.\" # BS - start boxed text
|
||||
.\" # ^y = starting y location
|
||||
.\" # ^b = 1
|
||||
.de BS
|
||||
.br
|
||||
.mk ^y
|
||||
.nr ^b 1u
|
||||
.if n .nf
|
||||
.if n .ti 0
|
||||
.if n \l'\\n(.lu\(ul'
|
||||
.if n .fi
|
||||
..
|
||||
.\" # BE - end boxed text (draw box now)
|
||||
.de BE
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
.ie n \l'\\n(^lu\(ul'
|
||||
.el \{\
|
||||
.\" Draw four-sided box normally, but don't draw top of
|
||||
.\" box if the box started on an earlier page.
|
||||
.ie !\\n(^b-1 \{\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.el \}\
|
||||
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
|
||||
.\}
|
||||
.\}
|
||||
.fi
|
||||
.br
|
||||
.nr ^b 0
|
||||
..
|
||||
.\" # VS - start vertical sidebar
|
||||
.\" # ^Y = starting y location
|
||||
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
|
||||
.de VS
|
||||
.if !"\\$2"" .br
|
||||
.mk ^Y
|
||||
.ie n 'mc \s12\(br\s0
|
||||
.el .nr ^v 1u
|
||||
..
|
||||
.\" # VE - end of vertical sidebar
|
||||
.de VE
|
||||
.ie n 'mc
|
||||
.el \{\
|
||||
.ev 2
|
||||
.nf
|
||||
.ti 0
|
||||
.mk ^t
|
||||
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
|
||||
.sp -1
|
||||
.fi
|
||||
.ev
|
||||
.\}
|
||||
.nr ^v 0
|
||||
..
|
||||
.\" # Special macro to handle page bottom: finish off current
|
||||
.\" # box/sidebar if in box/sidebar mode, then invoked standard
|
||||
.\" # page bottom macro.
|
||||
.de ^B
|
||||
.ev 2
|
||||
'ti 0
|
||||
'nf
|
||||
.mk ^t
|
||||
.if \\n(^b \{\
|
||||
.\" Draw three-sided box if this is the box's first page,
|
||||
.\" draw two sides but no top otherwise.
|
||||
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.nr ^x \\n(^tu+1v-\\n(^Yu
|
||||
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
|
||||
.\}
|
||||
.bp
|
||||
'fi
|
||||
.ev
|
||||
.if \\n(^b \{\
|
||||
.mk ^y
|
||||
.nr ^b 2
|
||||
.\}
|
||||
.if \\n(^v \{\
|
||||
.mk ^Y
|
||||
.\}
|
||||
..
|
||||
.\" # DS - begin display
|
||||
.de DS
|
||||
.RS
|
||||
.nf
|
||||
.sp
|
||||
..
|
||||
.\" # DE - end display
|
||||
.de DE
|
||||
.fi
|
||||
.RE
|
||||
.sp
|
||||
..
|
||||
.\" # SO - start of list of standard options
|
||||
.de SO
|
||||
'ie '\\$1'' .ds So \\fBoptions\\fR
|
||||
'el .ds So \\fB\\$1\\fR
|
||||
.SH "STANDARD OPTIONS"
|
||||
.LP
|
||||
.nf
|
||||
.ta 5.5c 11c
|
||||
.ft B
|
||||
..
|
||||
.\" # SE - end of list of standard options
|
||||
.de SE
|
||||
.fi
|
||||
.ft R
|
||||
.LP
|
||||
See the \\*(So manual entry for details on the standard options.
|
||||
..
|
||||
.\" # OP - start of full description for a single option
|
||||
.de OP
|
||||
.LP
|
||||
.nf
|
||||
.ta 4c
|
||||
Command-Line Name: \\fB\\$1\\fR
|
||||
Database Name: \\fB\\$2\\fR
|
||||
Database Class: \\fB\\$3\\fR
|
||||
.fi
|
||||
.IP
|
||||
..
|
||||
.\" # CS - begin code excerpt
|
||||
.de CS
|
||||
.RS
|
||||
.nf
|
||||
.ta .25i .5i .75i 1i
|
||||
..
|
||||
.\" # CE - end code excerpt
|
||||
.de CE
|
||||
.fi
|
||||
.RE
|
||||
..
|
||||
.\" # UL - underline word
|
||||
.de UL
|
||||
\\$1\l'|0\(ul'\\$2
|
||||
..
|
||||
.\" # QW - apply quotation marks to word
|
||||
.de QW
|
||||
.ie '\\*(lq'"' ``\\$1''\\$2
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\$2
|
||||
..
|
||||
.\" # PQ - apply parens and quotation marks to word
|
||||
.de PQ
|
||||
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
|
||||
..
|
||||
.\" # QR - quoted range
|
||||
.de QR
|
||||
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
|
||||
.\"" fix emacs highlighting
|
||||
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
|
||||
..
|
||||
.\" # MT - "empty" string
|
||||
.de MT
|
||||
.QW ""
|
||||
..
|
||||
.BS
|
||||
.SH NAME
|
||||
ttrace \- Trace-based interpreter initialization
|
||||
.SH SYNOPSIS
|
||||
package require \fBTcl 8\&.4\fR
|
||||
.sp
|
||||
package require \fBThread ?2\&.8?\fR
|
||||
.sp
|
||||
\fBttrace::eval\fR \fIarg\fR ?arg \&.\&.\&.?
|
||||
.sp
|
||||
\fBttrace::enable\fR
|
||||
.sp
|
||||
\fBttrace::disable\fR
|
||||
.sp
|
||||
\fBttrace::cleanup\fR
|
||||
.sp
|
||||
\fBttrace::update\fR ?epoch?
|
||||
.sp
|
||||
\fBttrace::getscript\fR
|
||||
.sp
|
||||
\fBttrace::atenable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::atdisable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::addtrace\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::addscript\fR \fIname\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::addresolver\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::addcleanup\fR \fIbody\fR
|
||||
.sp
|
||||
\fBttrace::addentry\fR \fIcmd\fR \fIvar\fR \fIval\fR
|
||||
.sp
|
||||
\fBttrace::getentry\fR \fIcmd\fR \fIvar\fR
|
||||
.sp
|
||||
\fBttrace::getentries\fR \fIcmd\fR ?pattern?
|
||||
.sp
|
||||
\fBttrace::delentry\fR \fIcmd\fR
|
||||
.sp
|
||||
\fBttrace::preload\fR \fIcmd\fR
|
||||
.sp
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
This package creates a framework for on-demand replication of the
|
||||
interpreter state accross threads in an multithreading application\&.
|
||||
It relies on the mechanics of Tcl command tracing and the Tcl
|
||||
\fBunknown\fR command and mechanism\&.
|
||||
.PP
|
||||
The package requires Tcl threading extension but can be alternatively
|
||||
used stand-alone within the AOLserver, a scalable webserver from
|
||||
America Online\&.
|
||||
.PP
|
||||
In a nutshell, a short sample illustrating the usage of the ttrace
|
||||
with the Tcl threading extension:
|
||||
.CS
|
||||
|
||||
|
||||
|
||||
% package require Ttrace
|
||||
2\&.8\&.0
|
||||
|
||||
% set t1 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1802800
|
||||
|
||||
% ttrace::eval {proc test args {return test-[thread::id]}}
|
||||
% thread::send $t1 test
|
||||
test-tid0x1802800
|
||||
|
||||
% set t2 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1804000
|
||||
|
||||
% thread::send $t2 test
|
||||
test-tid0x1804000
|
||||
|
||||
|
||||
.CE
|
||||
.PP
|
||||
As seen from above, the \fBttrace::eval\fR and \fBttrace::update\fR
|
||||
commands are used to create a thread-wide definition of a simple
|
||||
Tcl procedure and replicate that definition to all, already existing
|
||||
or later created, threads\&.
|
||||
.SH "USER COMMANDS"
|
||||
This section describes user-level commands\&. Those commands can be
|
||||
used by script writers to control the execution of the tracing
|
||||
framework\&.
|
||||
.TP
|
||||
\fBttrace::eval\fR \fIarg\fR ?arg \&.\&.\&.?
|
||||
This command concatenates given arguments and evaluates the resulting
|
||||
Tcl command with trace framework enabled\&. If the command execution
|
||||
was ok, it takes necessary steps to automatically propagate the
|
||||
trace epoch change to all threads in the application\&.
|
||||
For AOLserver, only newly created threads actually receive the
|
||||
epoch change\&. For the Tcl threading extension, all threads created by
|
||||
the extension are automatically updated\&. If the command execution
|
||||
resulted in Tcl error, no state propagation takes place\&.
|
||||
.sp
|
||||
This is the most important user-level command of the package as
|
||||
it wraps most of the commands described below\&. This greatly
|
||||
simplifies things, because user need to learn just this (one)
|
||||
command in order to effectively use the package\&. Other commands,
|
||||
as desribed below, are included mostly for the sake of completeness\&.
|
||||
.TP
|
||||
\fBttrace::enable\fR
|
||||
Activates all registered callbacks in the framework
|
||||
and starts a new trace epoch\&. The trace epoch encapsulates all
|
||||
changes done to the interpreter during the time traces are activated\&.
|
||||
.TP
|
||||
\fBttrace::disable\fR
|
||||
Deactivates all registered callbacks in the framework
|
||||
and closes the current trace epoch\&.
|
||||
.TP
|
||||
\fBttrace::cleanup\fR
|
||||
Used to clean-up all on-demand loaded resources in the interpreter\&.
|
||||
It effectively brings Tcl interpreter to its pristine state\&.
|
||||
.TP
|
||||
\fBttrace::update\fR ?epoch?
|
||||
Used to refresh the state of the interpreter to match the optional
|
||||
trace ?epoch?\&. If the optional ?epoch? is not given, it takes
|
||||
the most recent trace epoch\&.
|
||||
.TP
|
||||
\fBttrace::getscript\fR
|
||||
Returns a synthetized Tcl script which may be sourced in any interpreter\&.
|
||||
This script sets the stage for the Tcl \fBunknown\fR command so it can
|
||||
load traced resources from the in-memory database\&. Normally, this command
|
||||
is automatically invoked by other higher-level commands like
|
||||
\fBttrace::eval\fR and \fBttrace::update\fR\&.
|
||||
.PP
|
||||
.SH "CALLBACK COMMANDS"
|
||||
A word upfront: the package already includes callbacks for tracing
|
||||
following Tcl commands: \fBproc\fR, \fBnamespace\fR, \fBvariable\fR,
|
||||
\fBload\fR, and \fBrename\fR\&. Additionaly, a set of callbacks for
|
||||
tracing resources (object, clasess) for the XOTcl v1\&.3\&.8+, an
|
||||
OO-extension to Tcl, is also provided\&.
|
||||
This gives a solid base for solving most of the real-life needs and
|
||||
serves as an example for people wanting to customize the package
|
||||
to cover their specific needs\&.
|
||||
.PP
|
||||
Below, you can find commands for registering callbacks in the
|
||||
framework and for writing callback scripts\&. These callbacks are
|
||||
invoked by the framework in order to gather interpreter state
|
||||
changes, build in-memory database, perform custom-cleanups and
|
||||
various other tasks\&.
|
||||
.TP
|
||||
\fBttrace::atenable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated at \fBttrace::enable\fR\&.
|
||||
Registered callbacks are activated on FIFO basis\&. The callback
|
||||
definition includes the name of the callback, \fIcmd\fR, a list
|
||||
of callback arguments, \fIarglist\fR and the \fIbody\fR of the
|
||||
callback\&. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl \fBproc\fR command\&.
|
||||
.TP
|
||||
\fBttrace::atdisable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated at \fBttrace::disable\fR\&.
|
||||
Registered callbacks are activated on FIFO basis\&. The callback
|
||||
definition includes the name of the callback, \fIcmd\fR, a list
|
||||
of callback arguments, \fIarglist\fR and the \fIbody\fR of the
|
||||
callback\&. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl \fBproc\fR command\&.
|
||||
.TP
|
||||
\fBttrace::addtrace\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated for tracing the Tcl
|
||||
\fBcmd\fR command\&. The callback definition includes the name of
|
||||
the Tcl command to trace, \fIcmd\fR, a list of callback arguments,
|
||||
\fIarglist\fR and the \fIbody\fR of the callback\&. Effectively,
|
||||
this actually resembles the call interface of the standard Tcl
|
||||
\fBproc\fR command\&.
|
||||
.TP
|
||||
\fBttrace::addscript\fR \fIname\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated for building a Tcl
|
||||
script to be passed to other interpreters\&. This script is
|
||||
used to set the stage for the Tcl \fBunknown\fR command\&.
|
||||
Registered callbacks are activated on FIFO basis\&.
|
||||
The callback definition includes the name of the callback,
|
||||
\fIname\fR and the \fIbody\fR of the callback\&.
|
||||
.TP
|
||||
\fBttrace::addresolver\fR \fIcmd\fR \fIarglist\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated by the overloaded Tcl
|
||||
\fBunknown\fR command\&.
|
||||
Registered callbacks are activated on FIFO basis\&.
|
||||
This callback is used to resolve the resource and load the
|
||||
resource in the current interpreter\&.
|
||||
.TP
|
||||
\fBttrace::addcleanup\fR \fIbody\fR
|
||||
Registers Tcl callback to be activated by the \fBtrace::cleanup\fR\&.
|
||||
Registered callbacks are activated on FIFO basis\&.
|
||||
.TP
|
||||
\fBttrace::addentry\fR \fIcmd\fR \fIvar\fR \fIval\fR
|
||||
Adds one entry to the named in-memory database\&.
|
||||
.TP
|
||||
\fBttrace::getentry\fR \fIcmd\fR \fIvar\fR
|
||||
Returns the value of the entry from the named in-memory database\&.
|
||||
.TP
|
||||
\fBttrace::getentries\fR \fIcmd\fR ?pattern?
|
||||
Returns names of all entries from the named in-memory database\&.
|
||||
.TP
|
||||
\fBttrace::delentry\fR \fIcmd\fR
|
||||
Deletes an entry from the named in-memory database\&.
|
||||
.TP
|
||||
\fBttrace::preload\fR \fIcmd\fR
|
||||
Registers the Tcl command to be loaded in the interpreter\&.
|
||||
Commands registered this way will always be the part of
|
||||
the interpreter and not be on-demand loaded by the Tcl
|
||||
\fBunknown\fR command\&.
|
||||
.PP
|
||||
.SH DISCUSSION
|
||||
Common introspective state-replication approaches use a custom Tcl
|
||||
script to introspect the running interpreter and synthesize another
|
||||
Tcl script to replicate this state in some other interpreter\&.
|
||||
This package, on the contrary, uses Tcl command traces\&. Command
|
||||
traces are registered on selected Tcl commands, like \fBproc\fR,
|
||||
\fBnamespace\fR, \fBload\fR and other standard (and/or user-defined)
|
||||
Tcl commands\&. When activated, those traces build an in-memory
|
||||
database of created resources\&. This database is used as a resource
|
||||
repository for the (overloaded) Tcl \fBunknown\fR command which
|
||||
creates the requested resource in the interpreter on demand\&.
|
||||
This way, users can update just one interpreter (master) in one
|
||||
thread and replicate that interpreter state (or part of it) to other
|
||||
threads/interpreters in the process\&.
|
||||
.PP
|
||||
Immediate benefit of such approach is the much smaller memory footprint
|
||||
of the application and much faster thread creation\&. By not actually
|
||||
loading all necessary procedures (and other resources) in every thread
|
||||
at the thread initialization time, but by deffering this to the time the
|
||||
resource is actually referenced, significant improvements in both
|
||||
memory consumption and thread initialization time can be achieved\&. Some
|
||||
tests have shown that memory footprint of an multithreading Tcl application
|
||||
went down more than three times and thread startup time was reduced for
|
||||
about 50 times\&. Note that your mileage may vary\&.
|
||||
Other benefits include much finer control about what (and when) gets
|
||||
replicated from the master to other Tcl thread/interpreters\&.
|
||||
.SH "SEE ALSO"
|
||||
thread, tpool, tsv
|
||||
.SH KEYWORDS
|
||||
command tracing, introspection
|
||||
611
pkgs/thread2.8.7/doc/thread.man
Normal file
611
pkgs/thread2.8.7/doc/thread.man
Normal file
@@ -0,0 +1,611 @@
|
||||
[comment {-*- tcl -*- doctools manpage}]
|
||||
[manpage_begin thread n 2.8]
|
||||
[moddesc {Tcl Threading}]
|
||||
[titledesc {Extension for script access to Tcl threading}]
|
||||
[require Tcl 8.4]
|
||||
[require Thread [opt 2.8]]
|
||||
|
||||
[description]
|
||||
The [package thread] extension creates threads that contain Tcl
|
||||
interpreters, and it lets you send scripts to those threads for
|
||||
evaluation.
|
||||
|
||||
Additionally, it provides script-level access to basic thread
|
||||
synchronization primitives, like mutexes and condition variables.
|
||||
|
||||
[section COMMANDS]
|
||||
This section describes commands for creating and destroying threads
|
||||
and sending scripts to threads for evaluation.
|
||||
|
||||
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd thread::create] [opt -joinable] [opt -preserved] [opt script]]
|
||||
|
||||
This command creates a thread that contains a Tcl interpreter.
|
||||
The Tcl interpreter either evaluates the optional [option script], if
|
||||
specified, or it waits in the event loop for scripts that arrive via
|
||||
the [cmd thread::send] command. The result, if any, of the
|
||||
optional [option script] is never returned to the caller.
|
||||
The result of [cmd thread::create] is the ID of the thread. This is
|
||||
the opaque handle which identifies the newly created thread for
|
||||
all other package commands. The handle of the thread goes out of scope
|
||||
automatically when thread is marked for exit
|
||||
(see the [cmd thread::release] command below).
|
||||
|
||||
[para]
|
||||
|
||||
If the optional [option script] argument contains the [cmd thread::wait]
|
||||
command the thread will enter into the event loop. If such command is not
|
||||
found in the [option script] the thread will run the [option script] to
|
||||
the end and exit. In that case, the handle may be safely ignored since it
|
||||
refers to a thread which does not exists any more at the time when the
|
||||
command returns.
|
||||
|
||||
[para]
|
||||
|
||||
Using flag [option -joinable] it is possible to create a joinable
|
||||
thread, i.e. one upon whose exit can be waited upon by using
|
||||
[cmd thread::join] command.
|
||||
Note that failure to join a thread created with [option -joinable] flag
|
||||
results in resource and memory leaks.
|
||||
|
||||
|
||||
[para]
|
||||
|
||||
Threads created by the [cmd thread::create] cannot be destroyed
|
||||
forcefully. Consequently, there is no corresponding thread destroy
|
||||
command. A thread may only be released using the [cmd thread::release]
|
||||
and if its internal reference count drops to zero, the thread is
|
||||
marked for exit. This kicks the thread out of the event loop
|
||||
servicing and the thread continues to execute commands passed in
|
||||
the [option script] argument, following the [cmd thread::wait]
|
||||
command. If this was the last command in the script, as usually the
|
||||
case, the thread will exit.
|
||||
|
||||
[para]
|
||||
|
||||
It is possible to create a situation in which it may be impossible
|
||||
to terminate the thread, for example by putting some endless loop
|
||||
after the [cmd thread::wait] or entering the event loop again by
|
||||
doing an vwait-type of command. In such cases, the thread may never
|
||||
exit. This is considered to be a bad practice and should be avoided
|
||||
if possible. This is best illustrated by the example below:
|
||||
|
||||
[example {
|
||||
# You should never do ...
|
||||
set tid [thread::create {
|
||||
package require Http
|
||||
thread::wait
|
||||
vwait forever ; # <-- this!
|
||||
}]
|
||||
}]
|
||||
|
||||
The thread created in the above example will never be able to exit.
|
||||
After it has been released with the last matching [cmd thread::release]
|
||||
call, the thread will jump out of the [cmd thread::wait] and continue
|
||||
to execute commands following. It will enter [cmd vwait] command and
|
||||
wait endlessly for events. There is no way one can terminate such thread,
|
||||
so you wouldn't want to do this!
|
||||
|
||||
[para]
|
||||
|
||||
Each newly created has its internal reference counter set to 0 (zero),
|
||||
i.e. it is unreserved. This counter gets incremented by a call to
|
||||
[cmd thread::preserve] and decremented by a call to [cmd thread::release]
|
||||
command. These two commands implement simple but effective thread
|
||||
reservation system and offer predictable and controllable thread
|
||||
termination capabilities. It is however possible to create initially
|
||||
preserved threads by using flag [option -preserved] of the
|
||||
[cmd thread::create] command. Threads created with this flag have the
|
||||
initial value of the reference counter of 1 (one), and are thus
|
||||
initially marked reserved.
|
||||
|
||||
|
||||
[call [cmd thread::preserve] [opt id]]
|
||||
|
||||
This command increments the thread reference counter. Each call
|
||||
to this command increments the reference counter by one (1).
|
||||
Command returns the value of the reference counter after the increment.
|
||||
If called with the optional thread [option id], the command preserves
|
||||
the given thread. Otherwise the current thread is preserved.
|
||||
|
||||
[para]
|
||||
|
||||
With reference counting, one can implement controlled access to a
|
||||
shared Tcl thread. By incrementing the reference counter, the
|
||||
caller signalizes that he/she wishes to use the thread for a longer
|
||||
period of time. By decrementing the counter, caller signalizes that
|
||||
he/she has finished using the thread.
|
||||
|
||||
[call [cmd thread::release] [opt -wait] [opt id]]
|
||||
|
||||
This command decrements the thread reference counter. Each call to
|
||||
this command decrements the reference counter by one (1).
|
||||
If called with the optional thread [option id], the command releases
|
||||
the given thread. Otherwise, the current thread is released.
|
||||
Command returns the value of the reference counter after the decrement.
|
||||
When the reference counter reaches zero (0), the target thread is
|
||||
marked for termination. You should not reference the thread after the
|
||||
[cmd thread::release] command returns zero or negative integer.
|
||||
The handle of the thread goes out of scope and should not be used any
|
||||
more. Any following reference to the same thread handle will result
|
||||
in Tcl error.
|
||||
|
||||
[para]
|
||||
|
||||
Optional flag [option -wait] instructs the caller thread to wait for
|
||||
the target thread to exit, if the effect of the command would result
|
||||
in termination of the target thread, i.e. if the return result would
|
||||
be zero (0). Without the flag, the caller thread does not wait for
|
||||
the target thread to exit. Care must be taken when using the
|
||||
[option -wait], since this may block the caller thread indefinitely.
|
||||
This option has been implemented for some special uses of the extension
|
||||
and is deprecated for regular use. Regular users should create joinable
|
||||
threads by using the [option -joinable] option of the [cmd thread::create]
|
||||
command and the [cmd thread::join] to wait for thread to exit.
|
||||
|
||||
[call [cmd thread::id]]
|
||||
|
||||
This command returns the ID of the current thread.
|
||||
|
||||
[call [cmd thread::errorproc] [opt procname]]
|
||||
|
||||
This command sets a handler for errors that occur in scripts sent
|
||||
asynchronously, using the [option -async] flag of the
|
||||
[cmd thread::send] command, to other threads. If no handler
|
||||
is specified, the current handler is returned. The empty string
|
||||
resets the handler to default (unspecified) value.
|
||||
An uncaught error in a thread causes an error message to be sent
|
||||
to the standard error channel. This default reporting scheme can
|
||||
be changed by registering a procedure which is called to report
|
||||
the error. The [arg procname] is called in the interpreter that
|
||||
invoked the [cmd thread::errorproc] command. The [arg procname]
|
||||
is called like this:
|
||||
|
||||
[example {
|
||||
myerrorproc thread_id errorInfo
|
||||
}]
|
||||
|
||||
[call [cmd thread::cancel] [opt -unwind] [arg id] [opt result]]
|
||||
|
||||
This command requires Tcl version 8.6 or higher.
|
||||
|
||||
[para]
|
||||
|
||||
Cancels the script being evaluated in the thread given by the [arg id]
|
||||
parameter. Without the [option -unwind] switch the evaluation stack for
|
||||
the interpreter is unwound until an enclosing catch command is found or
|
||||
there are no further invocations of the interpreter left on the call
|
||||
stack. With the [option -unwind] switch the evaluation stack for the
|
||||
interpreter is unwound without regard to any intervening catch command
|
||||
until there are no further invocations of the interpreter left on the
|
||||
call stack. If [arg result] is present, it will be used as the error
|
||||
message string; otherwise, a default error message string will be used.
|
||||
|
||||
[call [cmd thread::unwind]]
|
||||
|
||||
Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with [cmd thread::preserve] and
|
||||
[cmd thread::release] commands. Support for [cmd thread::unwind]
|
||||
command will disappear in some future major release of the extension.
|
||||
[para]
|
||||
This command stops a prior [cmd thread::wait] command. Execution of
|
||||
the script passed to newly created thread will continue from the
|
||||
[cmd thread::wait] command. If [cmd thread::wait] was the last command
|
||||
in the script, the thread will exit. The command returns empty result
|
||||
but may trigger Tcl error with the message "target thread died" in some
|
||||
situations.
|
||||
|
||||
|
||||
[call [cmd thread::exit] [opt status]]
|
||||
|
||||
Use of this command is deprecated in favour of more advanced thread
|
||||
reservation system implemented with [cmd thread::preserve] and
|
||||
[cmd thread::release] commands. Support for [cmd thread::exit]
|
||||
command will disappear in some future major release of the extension.
|
||||
[para]
|
||||
This command forces a thread stuck in the [cmd thread::wait] command to
|
||||
unconditionally exit. The thread's exit status defaults to 666 and can be
|
||||
specified using the optional [arg status] argument. The execution of
|
||||
[cmd thread::exit] command is guaranteed to leave the program memory in the
|
||||
inconsistent state, produce memory leaks and otherwise affect other subsystem(s)
|
||||
of the Tcl application in an unpredictable manner. The command returns empty
|
||||
result but may trigger Tcl error with the message "target thread died" in some
|
||||
situations.
|
||||
|
||||
[call [cmd thread::names]]
|
||||
|
||||
This command returns a list of thread IDs. These are only for
|
||||
threads that have been created via [cmd thread::create] command.
|
||||
If your application creates other threads at the C level, they
|
||||
are not reported by this command.
|
||||
|
||||
|
||||
[call [cmd thread::exists] [arg id]]
|
||||
|
||||
Returns true (1) if thread given by the [arg id] parameter exists,
|
||||
false (0) otherwise. This applies only for threads that have
|
||||
been created via [cmd thread::create] command.
|
||||
|
||||
|
||||
[call [cmd thread::send] [opt -async] [opt -head] [arg id] [arg script] [opt varname]]
|
||||
|
||||
This command passes a [arg script] to another thread and, optionally,
|
||||
waits for the result. If the [option -async] flag is specified, the
|
||||
command does not wait for the result and it returns empty string.
|
||||
The target thread must enter it's event loop in order to receive
|
||||
scripts sent via this command. This is done by default for threads
|
||||
created without a startup script. Threads can enter the event loop
|
||||
explicitly by calling [cmd thread::wait] or any other relevant Tcl/Tk
|
||||
command, like [cmd update], [cmd vwait], etc.
|
||||
|
||||
[para]
|
||||
|
||||
Optional [option varname] specifies name of the variable to store
|
||||
the result of the [arg script]. Without the [option -async] flag,
|
||||
the command returns the evaluation code, similarly to the standard
|
||||
Tcl [cmd catch] command. If, however, the [option -async] flag is
|
||||
specified, the command returns immediately and caller can later
|
||||
[cmd vwait] on [opt varname] to get the result of the passed [arg script]
|
||||
|
||||
[example {
|
||||
set t1 [thread::create]
|
||||
set t2 [thread::create]
|
||||
thread::send -async $t1 "set a 1" result
|
||||
thread::send -async $t2 "set b 2" result
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
vwait result
|
||||
}
|
||||
}]
|
||||
|
||||
In the above example, two threads were fed work and both of them were
|
||||
instructed to signalize the same variable "result" in the calling thread.
|
||||
The caller entered the event loop twice to get both results. Note,
|
||||
however, that the order of the received results may vary, depending on
|
||||
the current system load, type of work done, etc, etc.
|
||||
|
||||
[para]
|
||||
|
||||
Many threads can simultaneously send scripts to the target thread for
|
||||
execution. All of them are entered into the event queue of the target
|
||||
thread and executed on the FIFO basis, intermingled with optional other
|
||||
events pending in the event queue of the target thread.
|
||||
Using the optional [opt -head] switch, scripts posted to the thread's
|
||||
event queue can be placed on the head, instead on the tail of the queue,
|
||||
thus being executed in the LIFO fashion.
|
||||
|
||||
|
||||
[call [cmd thread::broadcast] [arg script]]
|
||||
|
||||
This command passes a [arg script] to all threads created by the
|
||||
package for execution. It does not wait for response from any of
|
||||
the threads.
|
||||
|
||||
[call [cmd thread::wait]]
|
||||
|
||||
This enters the event loop so a thread can receive messages from
|
||||
the [cmd thread::send] command. This command should only be used
|
||||
within the script passed to the [cmd thread::create]. It should
|
||||
be the very last command in the script. If this is not the case,
|
||||
the exiting thread will continue executing the script lines past
|
||||
the [cmd thread::wait] which is usually not what you want and/or
|
||||
expect.
|
||||
|
||||
[example {
|
||||
set t1 [thread::create {
|
||||
#
|
||||
# Do some initialization work here
|
||||
#
|
||||
thread::wait ; # Enter the event loop
|
||||
}]
|
||||
}]
|
||||
|
||||
[call [cmd thread::eval] [opt {-lock mutex}] [arg arg] [opt {arg ...}]]
|
||||
|
||||
This command concatenates passed arguments and evaluates the
|
||||
resulting script under the mutex protection. If no mutex is
|
||||
specified by using the [opt {-lock mutex}] optional argument,
|
||||
the internal static mutex is used.
|
||||
|
||||
|
||||
[call [cmd thread::join] [arg id]]
|
||||
|
||||
This command waits for the thread with ID [arg id] to exit and
|
||||
then returns it's exit code. Errors will be returned for threads
|
||||
which are not joinable or already waited upon by another thread.
|
||||
Upon the join the handle of the thread has gone out of scope and
|
||||
should not be used any more.
|
||||
|
||||
|
||||
[call [cmd thread::configure] [arg id] [opt option] [opt value] [opt ...]]
|
||||
|
||||
This command configures various low-level aspects of the thread with
|
||||
ID [arg id] in the similar way as the standard Tcl command
|
||||
[cmd fconfigure] configures some Tcl channel options. Options currently
|
||||
supported are: [option -eventmark] and [option -unwindonerror].
|
||||
|
||||
[para]
|
||||
|
||||
The [option -eventmark] option, when set, limits the number of
|
||||
asynchronously posted scripts to the thread event loop.
|
||||
The [cmd {thread::send -async}] command will block until the number
|
||||
of pending scripts in the event loop does not drop below the value
|
||||
configured with [option -eventmark]. Default value for the
|
||||
[option -eventmark] is 0 (zero) which effectively disables the checking,
|
||||
i.e. allows for unlimited number of posted scripts.
|
||||
|
||||
[para]
|
||||
|
||||
The [option -unwindonerror] option, when set, causes the
|
||||
target thread to unwind if the result of the script processing
|
||||
resulted in error. Default value for the [option -unwindonerror]
|
||||
is 0 (false), i.e. thread continues to process scripts after one
|
||||
of the posted scripts fails.
|
||||
|
||||
|
||||
[call [cmd thread::transfer] [arg id] [arg channel]]
|
||||
|
||||
This moves the specified [arg channel] from the current thread
|
||||
and interpreter to the main interpreter of the thread with the
|
||||
given [arg id]. After the move the current interpreter has no
|
||||
access to the channel any more, but the main interpreter of the
|
||||
target thread will be able to use it from now on.
|
||||
The command waits until the other thread has incorporated the
|
||||
channel. Because of this it is possible to deadlock the
|
||||
participating threads by commanding the other through a
|
||||
synchronous [cmd thread::send] to transfer a channel to us.
|
||||
This easily extends into longer loops of threads waiting for
|
||||
each other. Other restrictions: the channel in question must
|
||||
not be shared among multiple interpreters running in the
|
||||
sending thread. This automatically excludes the special channels
|
||||
for standard input, output and error.
|
||||
|
||||
[para]
|
||||
|
||||
Due to the internal Tcl core implementation and the restriction on
|
||||
transferring shared channels, one has to take extra measures when
|
||||
transferring socket channels created by accepting the connection
|
||||
out of the [cmd socket] commands callback procedures:
|
||||
|
||||
[example {
|
||||
socket -server _Accept 2200
|
||||
proc _Accept {s ipaddr port} {
|
||||
after idle [list Accept $s $ipaddr $port]
|
||||
}
|
||||
proc Accept {s ipaddr port} {
|
||||
set tid [thread::create]
|
||||
thread::transfer $tid $s
|
||||
}
|
||||
}]
|
||||
|
||||
[call [cmd thread::detach] [arg channel]]
|
||||
|
||||
This detaches the specified [arg channel] from the current thread and
|
||||
interpreter. After that, the current interpreter has no access to the
|
||||
channel any more. The channel is in the parked state until some other
|
||||
(or the same) thread attaches the channel again with [cmd thread::attach].
|
||||
Restrictions: same as for transferring shared channels with the
|
||||
[cmd thread::transfer] command.
|
||||
|
||||
[call [cmd thread::attach] [arg channel]]
|
||||
|
||||
This attaches the previously detached [arg channel] in the
|
||||
current thread/interpreter. For already existing channels,
|
||||
the command does nothing, i.e. it is not an error to attach the
|
||||
same channel more than once. The first operation will actually
|
||||
perform the operation, while all subsequent operation will just
|
||||
do nothing. Command throws error if the [arg channel] cannot be
|
||||
found in the list of detached channels and/or in the current
|
||||
interpreter.
|
||||
|
||||
[call [cmd thread::mutex]]
|
||||
|
||||
Mutexes are most common thread synchronization primitives.
|
||||
They are used to synchronize access from two or more threads to one or
|
||||
more shared resources. This command provides script-level access to
|
||||
exclusive and/or recursive mutexes. Exclusive mutexes can be locked
|
||||
only once by one thread, while recursive mutexes can be locked many
|
||||
times by the same thread. For recursive mutexes, number of lock and
|
||||
unlock operations must match, otherwise, the mutex will never be
|
||||
released, which would lead to various deadlock situations.
|
||||
[para]
|
||||
Care has to be taken when using mutexes in an multithreading program.
|
||||
Improper use of mutexes may lead to various deadlock situations,
|
||||
especially when using exclusive mutexes.
|
||||
|
||||
[para]
|
||||
|
||||
The [cmd thread::mutex] command supports following subcommands and options:
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd thread::mutex] [method create] [opt -recursive]]
|
||||
|
||||
Creates the mutex and returns it's opaque handle. This handle
|
||||
should be used for any future reference to the newly created mutex.
|
||||
If no optional [opt -recursive] argument was specified, the command
|
||||
creates the exclusive mutex. With the [opt -recursive] argument,
|
||||
the command creates a recursive mutex.
|
||||
|
||||
[call [cmd thread::mutex] [method destroy] [arg mutex]]
|
||||
|
||||
Destroys the [arg mutex]. Mutex should be in unlocked state before
|
||||
the destroy attempt. If the mutex is locked, the command will throw
|
||||
Tcl error.
|
||||
|
||||
[call [cmd thread::mutex] [method lock] [arg mutex]]
|
||||
|
||||
Locks the [arg mutex]. Locking the exclusive mutex may throw Tcl
|
||||
error if on attempt to lock the same mutex twice from the same
|
||||
thread. If your program logic forces you to lock the same mutex
|
||||
twice or more from the same thread (this may happen in recursive
|
||||
procedure invocations) you should consider using the recursive mutexes.
|
||||
|
||||
[call [cmd thread::mutex] [method unlock] [arg mutex]]
|
||||
|
||||
Unlocks the [arg mutex] so some other thread may lock it again.
|
||||
Attempt to unlock the already unlocked mutex will throw Tcl error.
|
||||
|
||||
[list_end]
|
||||
|
||||
[para]
|
||||
|
||||
[call [cmd thread::rwmutex]]
|
||||
|
||||
This command creates many-readers/single-writer mutexes. Reader/writer
|
||||
mutexes allow you to serialize access to a shared resource more optimally.
|
||||
In situations where a shared resource gets mostly read and seldom modified,
|
||||
you might gain some performance by using reader/writer mutexes instead of
|
||||
exclusive or recursive mutexes.
|
||||
[para]
|
||||
For reading the resource, thread should obtain a read lock on the resource.
|
||||
Read lock is non-exclusive, meaning that more than one thread can
|
||||
obtain a read lock to the same resource, without waiting on other readers.
|
||||
For changing the resource, however, a thread must obtain a exclusive
|
||||
write lock. This lock effectively blocks all threads from gaining the
|
||||
read-lock while the resource is been modified by the writer thread.
|
||||
Only after the write lock has been released, the resource may be read-locked
|
||||
again.
|
||||
|
||||
[para]
|
||||
|
||||
The [cmd thread::rwmutex] command supports following subcommands and options:
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd thread::rwmutex] [method create]]
|
||||
|
||||
Creates the reader/writer mutex and returns it's opaque handle.
|
||||
This handle should be used for any future reference to the newly
|
||||
created mutex.
|
||||
|
||||
[call [cmd thread::rwmutex] [method destroy] [arg mutex]]
|
||||
|
||||
Destroys the reader/writer [arg mutex]. If the mutex is already locked,
|
||||
attempt to destroy it will throw Tcl error.
|
||||
|
||||
[call [cmd thread::rwmutex] [method rlock] [arg mutex]]
|
||||
|
||||
Locks the [arg mutex] for reading. More than one thread may read-lock
|
||||
the same [arg mutex] at the same time.
|
||||
|
||||
[call [cmd thread::rwmutex] [method wlock] [arg mutex]]
|
||||
|
||||
Locks the [arg mutex] for writing. Only one thread may write-lock
|
||||
the same [arg mutex] at the same time. Attempt to write-lock same
|
||||
[arg mutex] twice from the same thread will throw Tcl error.
|
||||
|
||||
[call [cmd thread::rwmutex] [method unlock] [arg mutex]]
|
||||
|
||||
Unlocks the [arg mutex] so some other thread may lock it again.
|
||||
Attempt to unlock already unlocked [arg mutex] will throw Tcl error.
|
||||
|
||||
[list_end]
|
||||
|
||||
[para]
|
||||
|
||||
[call [cmd thread::cond]]
|
||||
|
||||
This command provides script-level access to condition variables.
|
||||
A condition variable creates a safe environment for the program
|
||||
to test some condition, sleep on it when false and be awakened
|
||||
when it might have become true. A condition variable is always
|
||||
used in the conjunction with an exclusive mutex. If you attempt
|
||||
to use other type of mutex in conjunction with the condition
|
||||
variable, a Tcl error will be thrown.
|
||||
|
||||
[para]
|
||||
|
||||
The command supports following subcommands and options:
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd thread::cond] [method create]]
|
||||
|
||||
Creates the condition variable and returns it's opaque handle.
|
||||
This handle should be used for any future reference to newly
|
||||
created condition variable.
|
||||
|
||||
[call [cmd thread::cond] [method destroy] [arg cond]]
|
||||
|
||||
Destroys condition variable [arg cond]. Extreme care has to be taken
|
||||
that nobody is using (i.e. waiting on) the condition variable,
|
||||
otherwise unexpected errors may happen.
|
||||
|
||||
[call [cmd thread::cond] [method notify] [arg cond]]
|
||||
|
||||
Wakes up all threads waiting on the condition variable [arg cond].
|
||||
|
||||
[call [cmd thread::cond] [method wait] [arg cond] [arg mutex] [opt ms]]
|
||||
|
||||
This command is used to suspend program execution until the condition
|
||||
variable [arg cond] has been signalled or the optional timer has expired.
|
||||
The exclusive [arg mutex] must be locked by the calling thread on entrance
|
||||
to this command. If the mutex is not locked, Tcl error is thrown.
|
||||
While waiting on the [arg cond], the command releases [arg mutex].
|
||||
Before returning to the calling thread, the command re-acquires the
|
||||
[arg mutex] again. Unlocking the [arg mutex] and waiting on the
|
||||
condition variable [arg cond] is done atomically.
|
||||
|
||||
[para]
|
||||
|
||||
The [option ms] command option, if given, must be an integer specifying
|
||||
time interval in milliseconds the command waits to be signalled.
|
||||
Otherwise the command waits on condition notify forever.
|
||||
|
||||
[para]
|
||||
|
||||
In multithreading programs, there are many situations where a thread has
|
||||
to wait for some event to happen until it is allowed to proceed.
|
||||
This is usually accomplished by repeatedly testing a condition under the
|
||||
mutex protection and waiting on the condition variable until the condition
|
||||
evaluates to true:
|
||||
|
||||
[example {
|
||||
set mutex [thread::mutex create]
|
||||
set cond [thread::cond create]
|
||||
|
||||
thread::mutex lock $mutex
|
||||
while {<some_condition_is_true>} {
|
||||
thread::cond wait $cond $mutex
|
||||
}
|
||||
# Do some work under mutex protection
|
||||
thread::mutex unlock $mutex
|
||||
}]
|
||||
|
||||
Repeated testing of the condition is needed since the condition variable
|
||||
may get signalled without the condition being actually changed (spurious
|
||||
thread wake-ups, for example).
|
||||
|
||||
[list_end]
|
||||
|
||||
[list_end]
|
||||
|
||||
[section DISCUSSION]
|
||||
The fundamental threading model in Tcl is that there can be one or
|
||||
more Tcl interpreters per thread, but each Tcl interpreter should
|
||||
only be used by a single thread which created it.
|
||||
A "shared memory" abstraction is awkward to provide in Tcl because
|
||||
Tcl makes assumptions about variable and data ownership. Therefore
|
||||
this extension supports a simple form of threading where the main
|
||||
thread can manage several background, or "worker" threads.
|
||||
For example, an event-driven server can pass requests to worker
|
||||
threads, and then await responses from worker threads or new client
|
||||
requests. Everything goes through the common Tcl event loop, so
|
||||
message passing between threads works naturally with event-driven I/O,
|
||||
[cmd vwait] on variables, and so forth. For the transfer of bulk
|
||||
information it is possible to move channels between the threads.
|
||||
|
||||
[para]
|
||||
|
||||
For advanced multithreading scripts, script-level access to two
|
||||
basic synchronization primitives, mutex and condition variables,
|
||||
is also supported.
|
||||
|
||||
[see_also tsv tpool ttrace [uri http://www.tcl.tk/doc/howto/thread_model.html]]
|
||||
|
||||
[keywords thread events {message passing} synchronization mutex]
|
||||
|
||||
[manpage_end]
|
||||
225
pkgs/thread2.8.7/doc/tpool.man
Normal file
225
pkgs/thread2.8.7/doc/tpool.man
Normal file
@@ -0,0 +1,225 @@
|
||||
[comment {-*- tcl -*- doctools manpage}]
|
||||
[manpage_begin tpool n 2.8]
|
||||
[moddesc {Tcl Threading}]
|
||||
[titledesc {Part of the Tcl threading extension implementing pools of worker threads.}]
|
||||
[require Tcl 8.4]
|
||||
[require Thread [opt 2.8]]
|
||||
|
||||
[description]
|
||||
This package creates and manages pools of worker threads. It allows you
|
||||
to post jobs to worker threads and wait for their completion. The
|
||||
threadpool implementation is Tcl event-loop aware. That means that any
|
||||
time a caller is forced to wait for an event (job being completed or
|
||||
a worker thread becoming idle or initialized), the implementation will
|
||||
enter the event loop and allow for servicing of other pending file or
|
||||
timer (or any other supported) events.
|
||||
|
||||
[section COMMANDS]
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd tpool::create] [opt options]]
|
||||
|
||||
This command creates new threadpool. It accepts several options as
|
||||
key-value pairs. Options are used to tune some threadpool parameters.
|
||||
The command returns the ID of the newly created threadpool.
|
||||
[para]
|
||||
Following options are supported:
|
||||
|
||||
[list_begin options]
|
||||
|
||||
[opt_def -minworkers [arg number]]
|
||||
Minimum number of worker threads needed for this threadpool instance.
|
||||
During threadpool creation, the implementation will create somany
|
||||
worker threads upfront and will keep at least number of them alive
|
||||
during the lifetime of the threadpool instance.
|
||||
Default value of this parameter is 0 (zero). which means that a newly
|
||||
threadpool will have no worker threads initially. All worker threads
|
||||
will be started on demand by callers running [cmd tpool::post] command
|
||||
and posting jobs to the job queue.
|
||||
|
||||
[opt_def -maxworkers [arg number]]
|
||||
Maximum number of worker threads allowed for this threadpool instance.
|
||||
If a new job is pending and there are no idle worker threads available,
|
||||
the implementation will try to create new worker thread. If the number
|
||||
of available worker threads is lower than the given number,
|
||||
new worker thread will start. The caller will automatically enter the
|
||||
event loop and wait until the worker thread has initialized. If. however,
|
||||
the number of available worker threads is equal to the given number,
|
||||
the caller will enter the event loop and wait for the first worker thread
|
||||
to get idle, thus ready to run the job.
|
||||
Default value of this parameter is 4 (four), which means that the
|
||||
threadpool instance will allow maximum of 4 worker threads running jobs
|
||||
or being idle waiting for new jobs to get posted to the job queue.
|
||||
|
||||
[opt_def -idletime [arg seconds]]
|
||||
Time in seconds an idle worker thread waits for the job to get posted
|
||||
to the job queue. If no job arrives during this interval and the time
|
||||
expires, the worker thread will check the number of currently available
|
||||
worker threads and if the number is higher than the number set by the
|
||||
[option minthreads] option, it will exit.
|
||||
If an [option exitscript] has been defined, the exiting worker thread
|
||||
will first run the script and then exit. Errors from the exit script,
|
||||
if any, are ignored.
|
||||
[para]
|
||||
The idle worker thread is not servicing the event loop. If you, however,
|
||||
put the worker thread into the event loop, by evaluating the
|
||||
[cmd vwait] or other related Tcl commands, the worker thread
|
||||
will not be in the idle state, hence the idle timer will not be
|
||||
taken into account.
|
||||
Default value for this option is unspecified.
|
||||
|
||||
[opt_def -initcmd [arg script]]
|
||||
Sets a Tcl script used to initialize new worker thread. This is usually
|
||||
used to load packages and commands in the worker, set default variables,
|
||||
create namespaces, and such. If the passed script runs into a Tcl error,
|
||||
the worker will not be created and the initiating command (either the
|
||||
[cmd tpool::create] or [cmd tpool::post]) will throw error.
|
||||
Default value for this option is unspecified, hence, the Tcl interpreter of
|
||||
the worker thread will contain just the initial set of Tcl commands.
|
||||
|
||||
[opt_def -exitcmd [arg script]]
|
||||
Sets a Tcl script run when the idle worker thread exits. This is normally
|
||||
used to cleanup the state of the worker thread, release reserved resources,
|
||||
cleanup memory and such.
|
||||
Default value for this option is unspecified, thus no Tcl script will run
|
||||
on the worker thread exit.
|
||||
|
||||
[list_end]
|
||||
|
||||
[para]
|
||||
|
||||
[call [cmd tpool::names]]
|
||||
|
||||
This command returns a list of IDs of threadpools created with the
|
||||
[cmd tpool::create] command. If no threadpools were found, the
|
||||
command will return empty list.
|
||||
|
||||
[call [cmd tpool::post] [opt -detached] [opt -nowait] [arg tpool] [arg script]]
|
||||
|
||||
This command sends a [arg script] to the target [arg tpool] threadpool
|
||||
for execution. The script will be executed in the first available idle
|
||||
worker thread. If there are no idle worker threads available, the command
|
||||
will create new one, enter the event loop and service events until the
|
||||
newly created thread is initialized. If the current number of worker
|
||||
threads is equal to the maximum number of worker threads, as defined
|
||||
during the threadpool creation, the command will enter the event loop and
|
||||
service events while waiting for one of the worker threads to become idle.
|
||||
If the optional [opt -nowait] argument is given, the command will not wait
|
||||
for one idle worker. It will just place the job in the pool's job queue
|
||||
and return immediately.
|
||||
[para]
|
||||
The command returns the ID of the posted job. This ID is used for subsequent
|
||||
[cmd tpool::wait], [cmd tpool::get] and [cmd tpool::cancel] commands to wait
|
||||
for and retrieve result of the posted script, or cancel the posted job
|
||||
respectively. If the optional [opt -detached] argument is specified, the
|
||||
command will post a detached job. A detached job can not be cancelled or
|
||||
waited upon and is not identified by the job ID.
|
||||
[para]
|
||||
If the threadpool [arg tpool] is not found in the list of active
|
||||
thread pools, the command will throw error. The error will also be triggered
|
||||
if the newly created worker thread fails to initialize.
|
||||
|
||||
[call [cmd tpool::wait] [arg tpool] [arg joblist] [opt varname]]
|
||||
|
||||
This command waits for one or many jobs, whose job IDs are given in the
|
||||
[arg joblist] to get processed by the worker thread(s). If none of the
|
||||
specified jobs are ready, the command will enter the event loop, service
|
||||
events and wait for the first job to get ready.
|
||||
[para]
|
||||
The command returns the list of completed job IDs. If the optional variable
|
||||
[opt varname] is given, it will be set to the list of jobs in the
|
||||
[arg joblist] which are still pending. If the threadpool [arg tpool]
|
||||
is not found in the list of active thread pools, the command will throw error.
|
||||
|
||||
[call [cmd tpool::cancel] [arg tpool] [arg joblist] [opt varname]]
|
||||
|
||||
This command cancels the previously posted jobs given by the [arg joblist]
|
||||
to the pool [arg tpool]. Job cancellation succeeds only for job still
|
||||
waiting to be processed. If the job is already being executed by one of
|
||||
the worker threads, the job will not be cancelled.
|
||||
The command returns the list of cancelled job IDs. If the optional variable
|
||||
[opt varname] is given, it will be set to the list of jobs in the
|
||||
[arg joblist] which were not cancelled. If the threadpool [arg tpool]
|
||||
is not found in the list of active thread pools, the command will throw error.
|
||||
|
||||
[call [cmd tpool::get] [arg tpool] [arg job]]
|
||||
|
||||
This command retrieves the result of the previously posted [arg job].
|
||||
Only results of jobs waited upon with the [cmd tpool::wait] command
|
||||
can be retrieved. If the execution of the script resulted in error,
|
||||
the command will throw the error and update the [var errorInfo] and
|
||||
[var errorCode] variables correspondingly. If the pool [arg tpool]
|
||||
is not found in the list of threadpools, the command will throw error.
|
||||
If the job [arg job] is not ready for retrieval, because it is currently
|
||||
being executed by the worker thread, the command will throw error.
|
||||
|
||||
[call [cmd tpool::preserve] [arg tpool]]
|
||||
|
||||
Each call to this command increments the reference counter of the
|
||||
threadpool [arg tpool] by one (1). Command returns the value of the
|
||||
reference counter after the increment.
|
||||
By incrementing the reference counter, the caller signalizes that
|
||||
he/she wishes to use the resource for a longer period of time.
|
||||
|
||||
[call [cmd tpool::release] [arg tpool]]
|
||||
|
||||
Each call to this command decrements the reference counter of the
|
||||
threadpool [arg tpool] by one (1).Command returns the value of the
|
||||
reference counter after the decrement.
|
||||
When the reference counter reaches zero (0), the threadpool [arg tpool]
|
||||
is marked for termination. You should not reference the threadpool
|
||||
after the [cmd tpool::release] command returns zero. The [arg tpool]
|
||||
handle goes out of scope and should not be used any more. Any following
|
||||
reference to the same threadpool handle will result in Tcl error.
|
||||
|
||||
[call [cmd tpool::suspend] [arg tpool]]
|
||||
|
||||
Suspends processing work on this queue. All pool workers are paused
|
||||
but additional work can be added to the pool. Note that adding the
|
||||
additional work will not increase the number of workers dynamically
|
||||
as the pool processing is suspended. Number of workers is maintained
|
||||
to the count that was found prior suspending worker activity.
|
||||
If you need to assure certain number of worker threads, use the
|
||||
[option minworkers] option of the [cmd tpool::create] command.
|
||||
|
||||
[call [cmd tpool::resume] [arg tpool]]
|
||||
|
||||
Resume processing work on this queue. All paused (suspended)
|
||||
workers are free to get work from the pool. Note that resuming pool
|
||||
operation will just let already created workers to proceed.
|
||||
It will not create additional worker threads to handle the work
|
||||
posted to the pool's work queue.
|
||||
|
||||
[list_end]
|
||||
|
||||
|
||||
[section DISCUSSION]
|
||||
|
||||
Threadpool is one of the most common threading paradigm when it comes
|
||||
to server applications handling a large number of relatively small tasks.
|
||||
A very simplistic model for building a server application would be to
|
||||
create a new thread each time a request arrives and service the request
|
||||
in the new thread. One of the disadvantages of this approach is that
|
||||
the overhead of creating a new thread for each request is significant;
|
||||
a server that created a new thread for each request would spend more time
|
||||
and consume more system resources in creating and destroying threads than
|
||||
in processing actual user requests. In addition to the overhead of
|
||||
creating and destroying threads, active threads consume system resources.
|
||||
Creating too many threads can cause the system to run out of memory or
|
||||
trash due to excessive memory consumption.
|
||||
[para]
|
||||
A thread pool offers a solution to both the problem of thread life-cycle
|
||||
overhead and the problem of resource trashing. By reusing threads for
|
||||
multiple tasks, the thread-creation overhead is spread over many tasks.
|
||||
As a bonus, because the thread already exists when a request arrives,
|
||||
the delay introduced by thread creation is eliminated. Thus, the request
|
||||
can be serviced immediately. Furthermore, by properly tuning the number
|
||||
of threads in the thread pool, resource thrashing may also be eliminated
|
||||
by forcing any request to wait until a thread is available to process it.
|
||||
|
||||
[see_also tsv ttrace thread]
|
||||
|
||||
[keywords thread threadpool]
|
||||
|
||||
[manpage_end]
|
||||
336
pkgs/thread2.8.7/doc/tsv.man
Normal file
336
pkgs/thread2.8.7/doc/tsv.man
Normal file
@@ -0,0 +1,336 @@
|
||||
[comment {-*- tcl -*- doctools manpage}]
|
||||
[manpage_begin tsv n 2.8]
|
||||
[moddesc {Tcl Threading}]
|
||||
[titledesc {Part of the Tcl threading extension allowing script level manipulation of data shared between threads.}]
|
||||
[require Tcl 8.4]
|
||||
[require Thread [opt 2.8]]
|
||||
|
||||
[description]
|
||||
This section describes commands implementing thread shared variables.
|
||||
A thread shared variable is very similar to a Tcl array but in
|
||||
contrast to a Tcl array it is created in shared memory and can
|
||||
be accessed from many threads at the same time. Important feature of
|
||||
thread shared variable is that each access to the variable is internally
|
||||
protected by a mutex so script programmer does not have to take care
|
||||
about locking the variable himself.
|
||||
[para]
|
||||
Thread shared variables are not bound to any thread explicitly. That
|
||||
means that when a thread which created any of thread shared variables
|
||||
exits, the variable and associated memory is not unset/reclaimed.
|
||||
User has to explicitly unset the variable to reclaim the memory
|
||||
consumed by the variable.
|
||||
|
||||
[section {ELEMENT COMMANDS}]
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd tsv::names] [opt pattern]]
|
||||
|
||||
Returns names of shared variables matching optional [opt pattern]
|
||||
or all known variables if pattern is omitted.
|
||||
|
||||
[call [cmd tsv::object] [arg varname] [arg element]]
|
||||
|
||||
Creates object accessor command for the [arg element] in the
|
||||
shared variable [arg varname]. Using this command, one can apply most
|
||||
of the other shared variable commands as method functions of
|
||||
the element object command. The object command is automatically
|
||||
deleted when the element which this command is pointing to is unset.
|
||||
|
||||
[example {
|
||||
% tsv::set foo bar "A shared string"
|
||||
% set string [tsv::object foo bar]
|
||||
% $string append " appended"
|
||||
=> A shared string appended
|
||||
}]
|
||||
|
||||
[call [cmd tsv::set] [arg varname] [arg element] [opt value]]
|
||||
|
||||
Sets the value of the [arg element] in the shared variable [arg varname]
|
||||
to [arg value] and returns the value to caller. The [arg value]
|
||||
may be omitted, in which case the command will return the current
|
||||
value of the element. If the element cannot be found, error is triggered.
|
||||
|
||||
[call [cmd tsv::get] [arg varname] [arg element] [opt namedvar]]
|
||||
|
||||
Retrieves the value of the [arg element] from the shared variable [arg varname].
|
||||
If the optional argument [arg namedvar] is given, the value is
|
||||
stored in the named variable. Return value of the command depends
|
||||
of the existence of the optional argument [arg namedvar].
|
||||
If the argument is omitted and the requested element cannot be found
|
||||
in the shared array, the command triggers error. If, however, the
|
||||
optional argument is given on the command line, the command returns
|
||||
true (1) if the element is found or false (0) if the element is not found.
|
||||
|
||||
[call [cmd tsv::unset] [arg varname] [opt element]]
|
||||
|
||||
Unsets the [arg element] from the shared variable [arg varname].
|
||||
If the optional element is not given, it deletes the variable.
|
||||
|
||||
[call [cmd tsv::exists] [arg varname] [arg element]]
|
||||
|
||||
Checks whether the [arg element] exists in the shared variable [arg varname]
|
||||
and returns true (1) if it does or false (0) if it doesn't.
|
||||
|
||||
[call [cmd tsv::pop] [arg varname] [arg element]]
|
||||
|
||||
Returns value of the [arg element] in the shared variable [arg varname]
|
||||
and unsets the element, all in one atomic operation.
|
||||
|
||||
[call [cmd tsv::move] [arg varname] [arg oldname] [arg newname]]
|
||||
|
||||
Renames the element [arg oldname] to the [arg newname] in the
|
||||
shared variable [arg varname]. This effectively performs an get/unset/set
|
||||
sequence of operations but all in one atomic step.
|
||||
|
||||
[call [cmd tsv::incr] [arg varname] [arg element] [opt count]]
|
||||
|
||||
Similar to standard Tcl [cmd incr] command but increments the value
|
||||
of the [arg element] in shared variable [arg varname] instead of
|
||||
the Tcl variable.
|
||||
|
||||
[call [cmd tsv::append] [arg varname] [arg element] [arg value] [opt {value ...}]]
|
||||
|
||||
Similar to standard Tcl [cmd append] command but appends one or more
|
||||
values to the [arg element] in shared variable [arg varname] instead of the
|
||||
Tcl variable.
|
||||
|
||||
[call [cmd tsv::lock] [arg varname] [arg arg] [opt {arg ...}]]
|
||||
|
||||
This command concatenates passed arguments and evaluates the
|
||||
resulting script under the internal mutex protection. During the
|
||||
script evaluation, the entire shared variable is locked. For shared
|
||||
variable commands within the script, internal locking is disabled
|
||||
so no deadlock can occur. It is also allowed to unset the shared
|
||||
variable from within the script. The shared variable is automatically
|
||||
created if it did not exists at the time of the first lock operation.
|
||||
|
||||
[example {
|
||||
% tsv::lock foo {
|
||||
tsv::lappend foo bar 1
|
||||
tsv::lappend foo bar 2
|
||||
puts stderr [tsv::set foo bar]
|
||||
tsv::unset foo
|
||||
}
|
||||
}]
|
||||
|
||||
[call [cmd tsv::handlers]]
|
||||
|
||||
Returns the names of all persistent storage handlers enabled at compile time.
|
||||
See [sectref {ARRAY COMMANDS}] for details.
|
||||
|
||||
[list_end]
|
||||
|
||||
[section {LIST COMMANDS}]
|
||||
|
||||
Those command are similar to the equivalently named Tcl command. The difference
|
||||
is that they operate on elements of shared arrays.
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd tsv::lappend] [arg varname] [arg element] [arg value] [opt {value ...}]]
|
||||
|
||||
Similar to standard Tcl [cmd lappend] command but appends one
|
||||
or more values to the [arg element] in shared variable [arg varname]
|
||||
instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::linsert] [arg varname] [arg element] [arg index] [arg value] [opt {value ...}]]
|
||||
|
||||
Similar to standard Tcl [cmd linsert] command but inserts one
|
||||
or more values at the [arg index] list position in the
|
||||
[arg element] in the shared variable [arg varname] instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::lreplace] [arg varname] [arg element] [arg first] [arg last] [opt {value ...}]]
|
||||
|
||||
Similar to standard Tcl [cmd lreplace] command but replaces one
|
||||
or more values between the [arg first] and [arg last] position
|
||||
in the [arg element] of the shared variable [arg varname] instead of
|
||||
the Tcl variable.
|
||||
|
||||
[call [cmd tsv::llength] [arg varname] [arg element]]
|
||||
|
||||
Similar to standard Tcl [cmd llength] command but returns length
|
||||
of the [arg element] in the shared variable [arg varname] instead of the Tcl
|
||||
variable.
|
||||
|
||||
[call [cmd tsv::lindex] [arg varname] [arg element] [opt index]]
|
||||
|
||||
Similar to standard Tcl [cmd lindex] command but returns the value
|
||||
at the [arg index] list position of the [arg element] from
|
||||
the shared variable [arg varname] instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::lrange] [arg varname] [arg element] [arg from] [arg to]]
|
||||
|
||||
Similar to standard Tcl [cmd lrange] command but returns values
|
||||
between [arg from] and [arg to] list positions from the
|
||||
[arg element] in the shared variable [arg varname] instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::lsearch] [arg varname] [arg element] [opt options] [arg pattern]]
|
||||
|
||||
Similar to standard Tcl [cmd lsearch] command but searches the [arg element]
|
||||
in the shared variable [arg varname] instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::lset] [arg varname] [arg element] [arg index] [opt {index ...}] [arg value]]
|
||||
|
||||
Similar to standard Tcl [cmd lset] command but sets the [arg element]
|
||||
in the shared variable [arg varname] instead of the Tcl variable.
|
||||
|
||||
[call [cmd tsv::lpop] [arg varname] [arg element] [opt index]]
|
||||
|
||||
Similar to the standard Tcl [cmd lindex] command but in addition to
|
||||
returning, it also splices the value out of the [arg element]
|
||||
from the shared variable [arg varname] in one atomic operation.
|
||||
In contrast to the Tcl [cmd lindex] command, this command returns
|
||||
no value to the caller.
|
||||
|
||||
[call [cmd tsv::lpush] [arg varname] [arg element] [opt index]]
|
||||
|
||||
This command performs the opposite of the [cmd tsv::lpop] command.
|
||||
As its counterpart, it returns no value to the caller.
|
||||
|
||||
[list_end]
|
||||
|
||||
[section {ARRAY COMMANDS}]
|
||||
|
||||
This command supports most of the options of the standard Tcl
|
||||
[cmd array] command. In addition to those, it allows binding
|
||||
a shared variable to some persistent storage databases. Currently the persistent
|
||||
options supported are the famous GNU Gdbm and LMDB. These options have to be
|
||||
selected during the package compilation time.
|
||||
The implementation provides hooks for defining other persistency layers, if
|
||||
needed.
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd {tsv::array set}] [arg varname] [arg list]]
|
||||
|
||||
Does the same as standard Tcl [cmd {array set}].
|
||||
|
||||
[call [cmd {tsv::array get}] [arg varname] [opt pattern]]
|
||||
|
||||
Does the same as standard Tcl [cmd {array get}].
|
||||
|
||||
[call [cmd {tsv::array names}] [arg varname] [opt pattern]]
|
||||
|
||||
Does the same as standard Tcl [cmd {array names}].
|
||||
|
||||
[call [cmd {tsv::array size}] [arg varname]]
|
||||
|
||||
Does the same as standard Tcl [cmd {array size}].
|
||||
|
||||
[call [cmd {tsv::array reset}] [arg varname] [arg list]]
|
||||
|
||||
Does the same as standard Tcl [cmd {array set}] but it clears
|
||||
the [arg varname] and sets new values from the list atomically.
|
||||
|
||||
[call [cmd {tsv::array bind}] [arg varname] [arg handle]]
|
||||
Binds the [arg varname] to the persistent storage [arg handle].
|
||||
The format of the [arg handle] is <handler>:<address>, where <handler> is
|
||||
"gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the
|
||||
database file.
|
||||
|
||||
[call [cmd {tsv::array unbind}] [arg varname]]
|
||||
Unbinds the shared [arg array] from its bound persistent storage.
|
||||
|
||||
[call [cmd {tsv::array isbound}] [arg varname]]
|
||||
Returns true (1) if the shared [arg varname] is bound to some
|
||||
persistent storage or zero (0) if not.
|
||||
|
||||
|
||||
[list_end]
|
||||
|
||||
[section {KEYED LIST COMMANDS}]
|
||||
|
||||
Keyed list commands are borrowed from the TclX package. Keyed lists provide
|
||||
a structured data type built upon standard Tcl lists. This is a functionality
|
||||
similar to structs in the C programming language.
|
||||
[para]
|
||||
A keyed list is a list in which each element contains a key and value
|
||||
pair. These element pairs are stored as lists themselves, where the key
|
||||
is the first element of the list, and the value is the second. The
|
||||
key-value pairs are referred to as fields. This is an example of a
|
||||
keyed list:
|
||||
|
||||
[example {
|
||||
{{NAME {Frank Zappa}} {JOB {musician and composer}}}
|
||||
}]
|
||||
|
||||
Fields may contain subfields; `.' is the separator character. Subfields
|
||||
are actually fields where the value is another keyed list. Thus the
|
||||
following list has the top level fields ID and NAME, and subfields
|
||||
NAME.FIRST and NAME.LAST:
|
||||
|
||||
[example {
|
||||
{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}
|
||||
}]
|
||||
|
||||
There is no limit to the recursive depth of subfields,
|
||||
allowing one to build complex data structures. Keyed lists are constructed
|
||||
and accessed via a number of commands. All keyed list management
|
||||
commands take the name of the variable containing the keyed list as an
|
||||
argument (i.e. passed by reference), rather than passing the list directly.
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd tsv::keyldel] [arg varname] [arg keylist] [arg key]]
|
||||
|
||||
Delete the field specified by [arg key] from the keyed list [arg keylist]
|
||||
in the shared variable [arg varname].
|
||||
This removes both the key and the value from the keyed list.
|
||||
|
||||
[call [cmd tsv::keylget] [arg varname] [arg keylist] [arg key] [opt retvar]]
|
||||
|
||||
Return the value associated with [arg key] from the keyed list [arg keylist]
|
||||
in the shared variable [arg varname].
|
||||
If the optional [arg retvar] is not specified, then the value will be
|
||||
returned as the result of the command. In this case, if key is not found
|
||||
in the list, an error will result.
|
||||
[para]
|
||||
If [arg retvar] is specified and [arg key] is in the list, then the value
|
||||
is returned in the variable [arg retvar] and the command returns 1 if the
|
||||
key was present within the list. If [arg key] isn't in the list, the
|
||||
command will return 0, and [arg retvar] will be left unchanged. If {} is
|
||||
specified for [arg retvar], the value is not returned, allowing the Tcl
|
||||
programmer to determine if a [arg key] is present in a keyed list without
|
||||
setting a variable as a side-effect.
|
||||
|
||||
[call [cmd tsv::keylkeys] [arg varname] [arg keylist] [opt key]]
|
||||
Return the a list of the keys in the keyed list [arg keylist] in the
|
||||
shared variable [arg varname]. If [arg key] is specified, then it is
|
||||
the name of a key field whose subfield keys are to be retrieved.
|
||||
|
||||
|
||||
[call [cmd tsv::keylset] [arg varname] [arg keylist] [arg key] [arg value] [opt {key value..}]]
|
||||
Set the value associated with [arg key], in the keyed list [arg keylist]
|
||||
to [arg value]. If the [arg keylist] does not exists, it is created.
|
||||
If [arg key] is not currently in the list, it will be added. If it already
|
||||
exists, [arg value] replaces the existing value. Multiple keywords and
|
||||
values may be specified, if desired.
|
||||
|
||||
[list_end]
|
||||
|
||||
|
||||
[section DISCUSSION]
|
||||
The current implementation of thread shared variables allows for easy and
|
||||
convenient access to data shared between different threads.
|
||||
Internally, the data is stored in Tcl objects and all package commands
|
||||
operate on internal data representation, thus minimizing shimmering and
|
||||
improving performance. Special care has been taken to assure that all
|
||||
object data is properly locked and deep-copied when moving objects between
|
||||
threads.
|
||||
[para]
|
||||
Due to the internal design of the Tcl core, there is no provision of full
|
||||
integration of shared variables within the Tcl syntax, unfortunately. All
|
||||
access to shared data must be performed with the supplied package commands.
|
||||
Also, variable traces are not supported. But even so, benefits of easy,
|
||||
simple and safe shared data manipulation outweighs imposed limitations.
|
||||
|
||||
[section CREDITS]
|
||||
Thread shared variables are inspired by the nsv interface found in
|
||||
AOLserver, a highly scalable Web server from America Online.
|
||||
|
||||
[see_also tpool ttrace thread]
|
||||
|
||||
[keywords threads synchronization locking {thread shared data}]
|
||||
|
||||
[manpage_end]
|
||||
230
pkgs/thread2.8.7/doc/ttrace.man
Normal file
230
pkgs/thread2.8.7/doc/ttrace.man
Normal file
@@ -0,0 +1,230 @@
|
||||
[comment {-*- tcl -*- doctools manpage}]
|
||||
[manpage_begin ttrace n 2.8]
|
||||
[moddesc {Tcl Threading}]
|
||||
[titledesc {Trace-based interpreter initialization}]
|
||||
[require Tcl 8.4]
|
||||
[require Thread [opt 2.8]]
|
||||
|
||||
[description]
|
||||
This package creates a framework for on-demand replication of the
|
||||
interpreter state across threads in an multithreading application.
|
||||
It relies on the mechanics of Tcl command tracing and the Tcl
|
||||
[cmd unknown] command and mechanism.
|
||||
[para]
|
||||
The package requires Tcl threading extension but can be alternatively
|
||||
used stand-alone within the AOLserver, a scalable webserver from
|
||||
America Online.
|
||||
[para]
|
||||
In a nutshell, a short sample illustrating the usage of the ttrace
|
||||
with the Tcl threading extension:
|
||||
|
||||
[example {
|
||||
|
||||
% package require Ttrace
|
||||
2.8.2
|
||||
|
||||
% set t1 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1802800
|
||||
|
||||
% ttrace::eval {proc test args {return test-[thread::id]}}
|
||||
% thread::send $t1 test
|
||||
test-tid0x1802800
|
||||
|
||||
% set t2 [thread::create {package require Ttrace; thread::wait}]
|
||||
tid0x1804000
|
||||
|
||||
% thread::send $t2 test
|
||||
test-tid0x1804000
|
||||
|
||||
}]
|
||||
[para]
|
||||
As seen from above, the [cmd ttrace::eval] and [cmd ttrace::update]
|
||||
commands are used to create a thread-wide definition of a simple
|
||||
Tcl procedure and replicate that definition to all, already existing
|
||||
or later created, threads.
|
||||
|
||||
[section {USER COMMANDS}]
|
||||
This section describes user-level commands. Those commands can be
|
||||
used by script writers to control the execution of the tracing
|
||||
framework.
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd ttrace::eval] [arg arg] [opt {arg ...}]]
|
||||
|
||||
This command concatenates given arguments and evaluates the resulting
|
||||
Tcl command with trace framework enabled. If the command execution
|
||||
was ok, it takes necessary steps to automatically propagate the
|
||||
trace epoch change to all threads in the application.
|
||||
For AOLserver, only newly created threads actually receive the
|
||||
epoch change. For the Tcl threading extension, all threads created by
|
||||
the extension are automatically updated. If the command execution
|
||||
resulted in Tcl error, no state propagation takes place.
|
||||
[para]
|
||||
This is the most important user-level command of the package as
|
||||
it wraps most of the commands described below. This greatly
|
||||
simplifies things, because user need to learn just this (one)
|
||||
command in order to effectively use the package. Other commands,
|
||||
as described below, are included mostly for the sake of completeness.
|
||||
|
||||
[call [cmd ttrace::enable]]
|
||||
|
||||
Activates all registered callbacks in the framework
|
||||
and starts a new trace epoch. The trace epoch encapsulates all
|
||||
changes done to the interpreter during the time traces are activated.
|
||||
|
||||
[call [cmd ttrace::disable]]
|
||||
|
||||
Deactivates all registered callbacks in the framework
|
||||
and closes the current trace epoch.
|
||||
|
||||
[call [cmd ttrace::cleanup]]
|
||||
|
||||
Used to clean-up all on-demand loaded resources in the interpreter.
|
||||
It effectively brings Tcl interpreter to its pristine state.
|
||||
|
||||
[call [cmd ttrace::update] [opt epoch]]
|
||||
|
||||
Used to refresh the state of the interpreter to match the optional
|
||||
trace [opt epoch]. If the optional [opt epoch] is not given, it takes
|
||||
the most recent trace epoch.
|
||||
|
||||
[call [cmd ttrace::getscript]]
|
||||
|
||||
Returns a synthesized Tcl script which may be sourced in any interpreter.
|
||||
This script sets the stage for the Tcl [cmd unknown] command so it can
|
||||
load traced resources from the in-memory database. Normally, this command
|
||||
is automatically invoked by other higher-level commands like
|
||||
[cmd ttrace::eval] and [cmd ttrace::update].
|
||||
|
||||
[list_end]
|
||||
|
||||
[section {CALLBACK COMMANDS}]
|
||||
A word upfront: the package already includes callbacks for tracing
|
||||
following Tcl commands: [cmd proc], [cmd namespace], [cmd variable],
|
||||
[cmd load], and [cmd rename]. Additionally, a set of callbacks for
|
||||
tracing resources (object, classes) for the XOTcl v1.3.8+, an
|
||||
OO-extension to Tcl, is also provided.
|
||||
This gives a solid base for solving most of the real-life needs and
|
||||
serves as an example for people wanting to customize the package
|
||||
to cover their specific needs.
|
||||
[para]
|
||||
Below, you can find commands for registering callbacks in the
|
||||
framework and for writing callback scripts. These callbacks are
|
||||
invoked by the framework in order to gather interpreter state
|
||||
changes, build in-memory database, perform custom-cleanups and
|
||||
various other tasks.
|
||||
|
||||
|
||||
[list_begin definitions]
|
||||
|
||||
[call [cmd ttrace::atenable] [arg cmd] [arg arglist] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated at [cmd ttrace::enable].
|
||||
Registered callbacks are activated on FIFO basis. The callback
|
||||
definition includes the name of the callback, [arg cmd], a list
|
||||
of callback arguments, [arg arglist] and the [arg body] of the
|
||||
callback. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl [cmd proc] command.
|
||||
|
||||
|
||||
[call [cmd ttrace::atdisable] [arg cmd] [arg arglist] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated at [cmd ttrace::disable].
|
||||
Registered callbacks are activated on FIFO basis. The callback
|
||||
definition includes the name of the callback, [arg cmd], a list
|
||||
of callback arguments, [arg arglist] and the [arg body] of the
|
||||
callback. Effectively, this actually resembles the call interface
|
||||
of the standard Tcl [cmd proc] command.
|
||||
|
||||
|
||||
[call [cmd ttrace::addtrace] [arg cmd] [arg arglist] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated for tracing the Tcl
|
||||
[cmd cmd] command. The callback definition includes the name of
|
||||
the Tcl command to trace, [arg cmd], a list of callback arguments,
|
||||
[arg arglist] and the [arg body] of the callback. Effectively,
|
||||
this actually resembles the call interface of the standard Tcl
|
||||
[cmd proc] command.
|
||||
|
||||
|
||||
[call [cmd ttrace::addscript] [arg name] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated for building a Tcl
|
||||
script to be passed to other interpreters. This script is
|
||||
used to set the stage for the Tcl [cmd unknown] command.
|
||||
Registered callbacks are activated on FIFO basis.
|
||||
The callback definition includes the name of the callback,
|
||||
[arg name] and the [arg body] of the callback.
|
||||
|
||||
[call [cmd ttrace::addresolver] [arg cmd] [arg arglist] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated by the overloaded Tcl
|
||||
[cmd unknown] command.
|
||||
Registered callbacks are activated on FIFO basis.
|
||||
This callback is used to resolve the resource and load the
|
||||
resource in the current interpreter.
|
||||
|
||||
[call [cmd ttrace::addcleanup] [arg body]]
|
||||
|
||||
Registers Tcl callback to be activated by the [cmd trace::cleanup].
|
||||
Registered callbacks are activated on FIFO basis.
|
||||
|
||||
[call [cmd ttrace::addentry] [arg cmd] [arg var] [arg val]]
|
||||
|
||||
Adds one entry to the named in-memory database.
|
||||
|
||||
[call [cmd ttrace::getentry] [arg cmd] [arg var]]
|
||||
|
||||
Returns the value of the entry from the named in-memory database.
|
||||
|
||||
[call [cmd ttrace::getentries] [arg cmd] [opt pattern]]
|
||||
|
||||
Returns names of all entries from the named in-memory database.
|
||||
|
||||
[call [cmd ttrace::delentry] [arg cmd]]
|
||||
|
||||
Deletes an entry from the named in-memory database.
|
||||
|
||||
[call [cmd ttrace::preload] [arg cmd]]
|
||||
|
||||
Registers the Tcl command to be loaded in the interpreter.
|
||||
Commands registered this way will always be the part of
|
||||
the interpreter and not be on-demand loaded by the Tcl
|
||||
[cmd unknown] command.
|
||||
|
||||
[list_end]
|
||||
|
||||
[section DISCUSSION]
|
||||
Common introspective state-replication approaches use a custom Tcl
|
||||
script to introspect the running interpreter and synthesize another
|
||||
Tcl script to replicate this state in some other interpreter.
|
||||
This package, on the contrary, uses Tcl command traces. Command
|
||||
traces are registered on selected Tcl commands, like [cmd proc],
|
||||
[cmd namespace], [cmd load] and other standard (and/or user-defined)
|
||||
Tcl commands. When activated, those traces build an in-memory
|
||||
database of created resources. This database is used as a resource
|
||||
repository for the (overloaded) Tcl [cmd unknown] command which
|
||||
creates the requested resource in the interpreter on demand.
|
||||
This way, users can update just one interpreter (master) in one
|
||||
thread and replicate that interpreter state (or part of it) to other
|
||||
threads/interpreters in the process.
|
||||
[para]
|
||||
Immediate benefit of such approach is the much smaller memory footprint
|
||||
of the application and much faster thread creation. By not actually
|
||||
loading all necessary procedures (and other resources) in every thread
|
||||
at the thread initialization time, but by deferring this to the time the
|
||||
resource is actually referenced, significant improvements in both
|
||||
memory consumption and thread initialization time can be achieved. Some
|
||||
tests have shown that memory footprint of an multithreading Tcl application
|
||||
went down more than three times and thread startup time was reduced for
|
||||
about 50 times. Note that your mileage may vary.
|
||||
|
||||
Other benefits include much finer control about what (and when) gets
|
||||
replicated from the master to other Tcl thread/interpreters.
|
||||
|
||||
[see_also tsv tpool thread]
|
||||
|
||||
[keywords {command tracing} introspection]
|
||||
|
||||
[manpage_end]
|
||||
Reference in New Issue
Block a user