0

First of all, this is a follow up to a previous question of mine.

I would like to use threading in Tcl but in collaboration with Itcl.

Here is a sample:

package require Itcl
package require Thread

::itcl::class ThreadTest {
  variable thread [thread::create {thread::wait}]
  variable isRunning 0

  method start {} {
    set isRunning 1
    thread::send $thread {
      proc loop {} {
        puts "thread running"

        if { $isRunning } {
          after 1000 loop
        }
      }
      loop
    }
  }

  method stop {} {
    set isRunning 0
  }
}

set t [ThreadTest \#auto]
$t start

vwait forever

However, when the condition statement tries to execute and check if the isRunning variable is true, I get a no such variable error. I understand that this is because a proc only has access to the global scope. However, in this situation, I would like to contain the variable local to the class.

Is there a way to accomplish this?

Community
  • 1
  • 1
elmt
  • 1,604
  • 14
  • 24

1 Answers1

1

Tcl variables are per-interpreter, and interpreters are strongly bound to single threads (which greatly reduces the number of global-level locks required). To do what you want, you need to use a shared variable. Luckily, support for them is included with the Thread package (documentation here). You might then rewrite your code like this:

package require Itcl
package require Thread

::itcl::class ThreadTest {
  variable thread [thread::create {thread::wait}]

  constructor {} {
    tsv::set isRunning $this 0
  }    
  method start {} {
    tsv::set isRunning $this 1
    thread::send $thread {
      proc loop {handle} {
        puts "thread running"

        if { [tsv::get isRunning $handle] } {
          after 1000 loop $handle
        }
      }
    }
    thread::send $thread [list loop $this]
  }

  method stop {} {
    tsv::set isRunning $this 0
  }
}

set t [ThreadTest \#auto]
$t start

vwait forever
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • Note that you need to pass in the object handle, `$this`, to the other thread so that it knows what's going on. Using `list` to build that message is the easiest method to get it right, though that can only ever build single commands. – Donal Fellows Dec 01 '10 at 11:55
  • The truly paranoid would use `[thread::id],$this` as the handle, but if there's only one master that's not a big deal. – Donal Fellows Dec 01 '10 at 11:59