Marco Maggi (Package updated on June 2003) This package provides the ability to create a set of variables and restrict access to them to a set of procedures. This is similar to the creation of an object or a namespace used to hold variables private for an object instance.
All the procedures are located in the "task" namespace.
[constructor varname ?...?] - Initialiases a new task and returns the task identifier. The arguments are variable names that are linked to the scope of the caller. This procedure behaves exactly like [global]: variables are not created, just linked to the current scope. Using the empty string as variable name will lead to undefined behaviour. "varname" is the public name of the variable, the real name is the one of a variable in a private namespace.
[destructor task] - Deletes all the task specific data associated to the task identified by "task" (one more task and I shot myself). After this invocation the task (bang!) identifier "task" is no longer valid. Returns the empty string.
[global task varname ?varname ...?] - Links task-specific global variables in the scope of the caller. This procedure behaves exactly like [global]: variables are not created, just linked to the current scope. Returns the empty string.
[globname task varname] - Returns the real name of a task global variable. This can be used, for example, in a call to [vwait].
[globset task varname value] - Stores a new value in a non-array variable.
[globget task varname] - Returns the value in a non-array variable.
As simple usage example take a look at the following code:
proc begin { task working_directory } { set task [task::constructor data pwd] set data 123 set pwd ... } proc routine { task args } { task::global $task data cd [task::globget $task pwd] ... set data ... ... } proc end { task } { task::global $task data # do something with "$data" task::destructor $task return } begin ::task routine ::task end ::task
The package code follows.
namespace eval task { namespace export \[a-z\]* variable counter 0 variable ns [namespace current] variable map array set map {} namespace eval tmp {} } proc task::constructor { args } { variable counter variable map variable ns while { [info exists map([incr counter])] } {} set map([set token $counter]) {} foreach varname $args { while { [info exists [set n ${ns}::tmp::[incr counter]]] } {} uplevel [list upvar [set map($token:$varname) $n] $varname] } return $token } proc task::destructor { token } { variable map # Some variables may be unexistent, only registered, so we use #"-nocomplain". foreach k [array names map $token:*] { unset -nocomplain -- $map($k) unset map($k) } unset map($token) return } proc task::global { token varname args } { variable map uplevel [list upvar $map($token:$varname) $varname] foreach varname $args { uplevel [list upvar $map($token:$varname) $varname] } return } proc task::globname { token varname } { variable map return $map($token:$varname) } proc task::globset { token varname value } { variable map set $map($token:$varname) $value return } proc task::globget { token varname } { variable map return [set $map($token:$varname)] }