Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tcllib tie package issue with remotearray datasource

10 views
Skip to first unread message

Bezoar

unread,
May 9, 2007, 12:41:31 PM5/9/07
to

A previous post wanted an easy way to update an array to/from a server
process to any other process that was listening so I automatically
thought of using the tcllib tie library as it had a remotearray data
source. I created a server to hold the remote array, an interactive
client that can change the values on the server, and a client that
does nothing but display changes made to the remote array on the
server. (Code below) However it does not work as advertised. The man
page for tie says:

"...Just tie several Tcl arrays in many client processes to a Tcl
array in a server and all changes to any of them will be distributed
to all."

The only way I could get it so the reader process was updated was to
re-establish the link via a new tie in a timed while loop. Debug
messges show the number of ties building ( as you would expect) but
tie ( on server ) does not iterate through them as it should. I'd
rather use a trace to detect changes as it allows other activities to
happen. What am I doing wrong or does the "remotearray" tie not
support what was advertised?

######## Server #####################
#!/opt/usr/bin/tclsh8.5
package require tie
global av forever
array set av ""
set forever 0
set port [ lindex $argv 0 ]
package require comm;
::comm::comm config -port $port -listen 1
::comm::comm debug 1
vwait forever
::comm::comm abort
exit 0
############ END #####################
######### Updater ###################
#!/opt/usr/bin/tclsh8.5
package require tie
global av forever
array set av ""
set forever 0
set port [ lindex $argv 0 ]
package require comm
tie::tie av -open remotearray av {comm::comm send} $port
puts "initial array"
set done 0
while { !$done } {
parray av
puts -nonewline stdout "Enter key or q to quit: "
flush stdout
gets stdin key
if { [string equal $key "q" ] } {
break;
}
set key [string trim $key]
puts -nonewline stdout "Enter value:"
flush stdout
gets stdin value
#update the remote array
if { [ catch { set av($key) \"$value\" } err ] != 0 } {
puts "$err"
}
}
############ END #####################
########### READER ###################
#!/opt/usr/bin/tclsh8.5
package require tie

proc arrayChanged { name index op } {
global av forever
upvar $name myArray
puts " $name\($index\) was $op"
switch -exact -- $op {
"read" {
;
}
"write" {
puts "array Changed"
parray myArray
}
"unset" {
puts "array removed"
puts "exiting..."
set forever 1
}
}

}
global av forever
array set av ""
set forever 0

set port [ lindex $argv 0 ]
package require comm
tie::tie av -open remotearray av {comm::comm send} $port
puts "initial array"
parray av
#what works but while loop not optimal
while { 1 } {
after 1000;
# this is necessary to get a refresh wont work without
tie::tie av -open remotearray av {comm::comm send} $port
parray av
}
# what I want to work
trace add variable av {read write unset } arrayChanged
vwait forever
::comm::comm abort
exit 0
########### End Reader #####################

To run open three or more terminals
in one run the server:

server.tcl <port>

in another run the updater:

updater.tcl <port>

in as many other terminals as you want run

reader.tcl <port>

use the updater to add key value pairs to the remote array
check behavior in reader window.

Thanks ahead of time

Carl

0 new messages