tsv(3tcl)
tsv π the Tcl threading extension's shared-variable era
okay bestie, welcome to tsv(3tcl) β this is part of the Tcl threading extension that lets you, from script level, mess with data that's shared between threads. it's giving "many threads, one variable, zero chaos" β¨
πΈ SYNOPSIS πΈ
package require Tcl 9.0
package require thread ?3.0?
tsv::names ?pattern?
tsv::object varname element
tsv::set varname element ?value?
tsv::get varname element ?namedvar?
tsv::unset varname ?element?
tsv::exists varname element
tsv::pop varname element
tsv::move varname oldname newname
tsv::incr varname element ?count?
tsv::append varname element value ?value ...?
tsv::lock varname arg ?arg ...?
tsv::handlers
tsv::lappend varname element value ?value ...?
tsv::linsert varname element index value ?value ...?
tsv::lreplace varname element first last ?value ...?
tsv::llength varname element
tsv::lindex varname element ?index?
tsv::lrange varname element from to
tsv::lsearch varname element ?options? pattern
tsv::lset varname element index ?index ...? value
tsv::lpop varname element ?index?
tsv::lpush varname element ?index?
tsv::array set varname list
tsv::array get varname ?pattern?
tsv::array names varname ?pattern?
tsv::array size varname
tsv::array reset varname list
tsv::array bind varname handle
tsv::array unbind varname
tsv::array isbound varname
tsv::keyldel varname keylist key
tsv::keylget varname keylist key ?retvar?
tsv::keylkeys varname keylist ?key?
tsv::keylset varname keylist key value ?key value..?
β¨ DESCRIPTION β¨
so this whole section is about the commands that give you thread shared variables. a thread shared variable is lowkey just like a Tcl array, but bestie β plot twist β it lives in shared memory and many threads can hit it at the same time. the iconic feature? every single access to the variable is internally protected by a mutex π so you, the script programmer, do not have to sit there worrying about locking the variable yourself. we love a self-locking queen. π
thread shared variables are not bound to any thread explicitly. what that means fr fr: when a thread that created one of these variables exits, the variable and its associated memory are not unset or reclaimed. nope. π the user has to explicitly unset the variable to reclaim the memory it's consuming. don't forget or it just... lingers. like an unread group chat.
π ELEMENT COMMANDS π
tsv::names ?pattern?
returns the names of shared variables matching the optional ?pattern?, or all known variables if pattern is omitted. slay.
tsv::object varname element
creates an object accessor command for the element in the shared variable varname. using this, you can apply most of the other shared variable commands as method functions of the element object command. and here's the cute part β the object command is automatically deleted when the element it's pointing to gets unset. it knows when to leave the party. β¨
% tsv::set foo bar "A shared string"
% set string [tsv::object foo bar]
% $string append " appended"
=> A shared string appended
tsv::set varname element ?value?
sets the value of the element in the shared variable varname to value and returns the value to the caller. you can omit value, in which case the command just hands you back the element's current value. if the element cannot be found, an error gets triggered. π
tsv::get varname element ?namedvar?
retrieves the value of the element from the shared variable varname. if the optional namedvar argument is given, the value gets stored in that named variable. the command's return value depends on whether namedvar was passed, so pay attention bestie π β if namedvar is omitted and the requested element can't be found in the shared array, the command triggers error. if the optional argument is given on the command line, the command returns true (1) when the element is found, or false (0) when it isn't.
tsv::unset varname ?element?
unsets the element from the shared variable varname. if the optional element isn't given, it deletes the whole variable. gone. poof. π¦
tsv::exists varname element
checks whether the element exists in the shared variable varname, returning true (1) if it does or false (0) if it doesn't. vibe check complete. β
tsv::pop varname element
returns the value of the element in the shared variable varname and unsets the element β all in one atomic operation. get it, remove it, no in-between. π
tsv::move varname oldname newname
renames the element oldname to newname in the shared variable varname. it effectively performs a get/unset/set sequence of operations, but all in one atomic step. glow-up, instantly. β¨
tsv::incr varname element ?count?
just like the standard Tcl incr command, except it increments the value of the element in shared variable varname instead of the Tcl variable. numbers going up, we love to see it. π
tsv::append varname element value ?value ...?
just like the standard Tcl append command, except it appends one or more values to the element in shared variable varname instead of the Tcl variable.
tsv::lock varname arg ?arg ...?
this command concatenates the passed arguments and evaluates the resulting script under the internal mutex protection. while that script is evaluating, the entire shared variable is locked. π for shared variable commands inside the script, internal locking is disabled, so no deadlock can occur. it's also allowed to unset the shared variable from within the script. and the shared variable gets automatically created if it didn't exist at the time of the first lock operation.
% tsv::lock foo {
tsv::lappend foo bar 1
tsv::lappend foo bar 2
puts stderr [tsv::set foo bar]
tsv::unset foo
}
tsv::handlers
returns the names of all persistent storage handlers enabled at compile time. see ARRAY COMMANDS for the deets. π«Ά
π¦ LIST COMMANDS π¦
these commands are similar to the equivalently named Tcl commands, except β plot twist β they operate on elements of shared arrays. same energy, shared memory. π
tsv::lappend varname element value ?value ...?
just like the standard Tcl lappend command, except it appends one or more values to the element in shared variable varname instead of the Tcl variable.
tsv::linsert varname element index value ?value ...?
just like the standard Tcl linsert command, except it inserts one or more values at the index list position in the element in the shared variable varname instead of the Tcl variable.
tsv::lreplace varname element first last ?value ...?
just like the standard Tcl lreplace command, except it replaces one or more values between the first and last position in the element of the shared variable varname instead of the Tcl variable.
tsv::llength varname element
just like the standard Tcl llength command, except it returns the length of the element in the shared variable varname instead of the Tcl variable.
tsv::lindex varname element ?index?
just like the standard Tcl lindex command, except it returns the value at the index list position of the element from the shared variable varname instead of the Tcl variable.
tsv::lrange varname element from to
just like the standard Tcl lrange command, except it returns values between the from and to list positions from the element in the shared variable varname instead of the Tcl variable.
tsv::lsearch varname element ?options? pattern
just like the standard Tcl lsearch command, except it searches the element in the shared variable varname instead of the Tcl variable.
tsv::lset varname element index ?index ...? value
just like the standard Tcl lset command, except it sets the element in the shared variable varname instead of the Tcl variable.
tsv::lpop varname element ?index?
just like the standard Tcl lindex command, except that in addition to returning, it also splices the value out of the element from the shared variable varname in one atomic operation. but heads up β in contrast to the Tcl lindex command, this command returns no value to the caller. π
tsv::lpush varname element ?index?
this command performs the opposite of the tsv::lpop command. and just like its counterpart, it returns no value to the caller. symmetric. iconic. π
π ARRAY COMMANDS π
this command supports most of the options of the standard Tcl array command. plus, it lets you bind 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 also provides hooks for defining other persistency layers, if you ever need that. π₯
tsv::array set varname list
does the same as standard Tcl array set.
tsv::array get varname ?pattern?
does the same as standard Tcl array get.
tsv::array names varname ?pattern?
does the same as standard Tcl array names.
tsv::array size varname
does the same as standard Tcl array size.
tsv::array reset varname list
does the same as standard Tcl array set, but it clears the varname and sets new values from the list β atomically. out with the old, in with the new, all in one breath. β¨
tsv::array bind varname handle
binds the varname to the persistent storage handle. the format of the handle is <handler>:<address>, where <handler> is "gdbm" for GNU Gdbm and "lmdb" for LMDB, and <address> is the path to the database file.
tsv::array unbind varname
unbinds the shared array from its bound persistent storage. it's free now. π¦
tsv::array isbound varname
returns true (1) if the shared varname is bound to some persistent storage, or zero (0) if not.
β¨ KEYED LIST COMMANDS β¨
ok so these ones are borrowed from the TclX package β keyed lists give you a whole structured data type built on top of regular Tcl lists, which is basically the Tcl version of structs in the C programming language. iykyk π
A keyed list is a list where every element holds a key and value pair. Those pairs are stored as lists themselves β the key is the first element of the list, the value is the second. And we call these key-value pairs fields. Here's a whole example bestie:
{{NAME {Frank Zappa}} {JOB {musician and composer}}}
Fields can also contain subfields, and . is the separator character. Subfields are literally just fields where the value is another keyed list. So this next one has top level fields ID and NAME, plus subfields NAME.FIRST and NAME.LAST:
{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}
There is no limit to the recursive depth of subfields β build whatever complex data structure your heart desires π¦. Keyed lists get constructed and accessed through a bunch of commands. And here's the thing: all keyed list management commands take the name of the variable containing the keyed list as an argument (i.e. passed by reference), instead of passing the list directly. not me always forgetting that π«Ά
π tsv::keyldel π
tsv::keyldel varname keylist key
Delete the field specified by key from the keyed list keylist in the shared variable varname. This removes both the key and the value from the keyed list. gone. deleted. periodt π
πΈ tsv::keylget πΈ
tsv::keylget varname keylist key ?retvar?
Return the value associated with key from the keyed list keylist in the shared variable varname. If the optional retvar is not specified, then the value gets returned as the result of the command. But heads up β in that case, if key is not found in the list, an error will result π.
If retvar is specified and key is in the list, then the value is returned in the variable retvar and the command returns 1 β meaning yes bestie, the key was present within the list. If key isn't in the list, the command will return 0, and retvar will be left unchanged. And if {} is specified for retvar, the value is not returned at all β which lets the Tcl programmer check whether a key is present in a keyed list without setting a variable as a side-effect. so clean β¨
π tsv::keylkeys π
tsv::keylkeys varname keylist ?key?
Return the a list of the keys in the keyed list keylist in the shared variable varname. If key is specified, then it's the name of a key field whose subfield keys are to be retrieved. yes, "the a list" β we keep it exactly as the manpage wrote it, no notes π
π¦ tsv::keylset π¦
tsv::keylset varname keylist key value ?key value..?
Set the value associated with key, in the keyed list keylist, to value. If the keylist does not exists, it is created. If key is not currently in the list, it will be added. If it already exists, value replaces the existing value. And you can pass multiple keywords and values if you want β go off π
π§ 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, which minimizes shimmering and improves performance π₯. Special care has been taken to assure that all object data is properly locked and deep-copied when moving objects between threads. very much main character energy tbh.
Due to the internal design of the Tcl core, there is unfortunately no provision of full integration of shared variables within the Tcl syntax π. All access to shared data must be performed with the supplied package commands. Also, variable traces are not supported. But even so β the benefits of easy, simple and safe shared data manipulation outweighs the imposed limitations. lowkey a fair trade bestie π«Ά
β CREDITS β
Thread shared variables are inspired by the nsv interface found in AOLserver, a highly scalable Web server from America Online. iconic lineage fr fr.
π SEE ALSO π
thread, tpool, ttrace
π KEYWORDS π
locking, synchronization, thread shared data, threads
and that's the whole page bestie, you ate that π this one came from the Tcl Threading source, version 3.0, and it's dated tsv(3tcl) β go forth and lock your shared data responsibly, no cap πβ¨
π¦ where this page comes from
- debian trixie: tcl9.0-thread 3.0.1-2+b1 Β· Tcl
- ubuntu questing: tcl9.0-thread 3.0.1-2
- ubuntu resolute: tcl9.0-thread 3.0.4-2 Β· Tcl
- ubuntu stonking: tcl-thread 1:3.0.6-1 Β· Tcl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms