[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]
