So far in my experience with Tcl (only a few days), I have discovered
than Tcl./Tk 8.1 is multi-threaded. While a procedure is running, the
user can hit a button and asynchronously set a variable. The procedure,
while it is running, can look at the newly modified variable and take
new action. I like this.
HOWEVER . . . . Then I put an "after 5000" command in my procedure. The
"after" command blocks the entire program, that is, every thread. Is
there an "after" variation which only blocks the thread the procedure is
running in? In POSIX terms, is there a pthread_sleep()?
Same question put differently: If I hit a button, the Tcl Event
Handler does not take action on the button until after the procedure's
"after" finishes. Can I interrupt a Tcl program while the program is in
the "after" time interval?
Brian
Brian Ceccarelli wrote:
>
> Dear Tcl Gurus,
>
> So far in my experience with Tcl (only a few days), I have discovered
> than Tcl./Tk 8.1 is multi-threaded. While a procedure is running, the
> user can hit a button and asynchronously set a variable. The procedure,
> while it is running, can look at the newly modified variable and take
> new action. I like this.
Actually, this is "event driven" programming. The Tcl Notifier is in
fact a separate thread, but ONLY if you built with --enable-threads
(or the equivalent on Windows) which is not the default.
> HOWEVER . . . . Then I put an "after 5000" command in my procedure. The
> "after" command blocks the entire program, that is, every thread. Is
> there an "after" variation which only blocks the thread the procedure is
> running in? In POSIX terms, is there a pthread_sleep()?
I think you want this:
after 5000 {set x 1}
vwait x
This will allow events to be handled (the GUI will be responsive) and
other events to occur (the vwait processes the event loop).
No, it is not multithreaded. It is event driven, which is different.
> HOWEVER . . . . Then I put an "after 5000" command in my procedure. The
> "after" command blocks the entire program, that is, every thread.
No, it blocks the _only_ thread.
> Is
> there an "after" variation which only blocks the thread the procedure is
> running in? In POSIX terms, is there a pthread_sleep()?
No.
>
> Same question put differently: If I hit a button, the Tcl Event
> Handler does not take action on the button until after the procedure's
> "after" finishes. Can I interrupt a Tcl program while the program is in
> the "after" time interval?
No. The theory is, if you do "after 5000" you are purposefully telling
the application to sleep for 5 seconds, which it is dutifully doing.
If you can describe why it is you think you need to use after in such a
manner, perhaps we can tell you a better way to accomplish the task. (if
I were a betting man, I'd bet what you are interested in is vwait).
--
Bryan Oakley mailto:oak...@channelpoint.com
ChannelPoint, Inc. http://purl.oclc.org/net/oakley
Eh-Eh... Expect to go through this a couple of times when 8.1 goes
final...
I am scared in advance by the drop of SNR of this group when this
explosive mix {threads, events, beginners} does burst,
(You guys had, by the way, been warned :^)
-Alex
The Tcl/Tk Event-Notifier is active, yes. But while the 1st procedure is
executing in my Tcl program, I can press a GUI button and set a variable.
The 1st procedure is still running.. This, by definition, is
multi-threaded. If the event notifier waited for the first procedure to
finish, and then set my variable, then I would declare, "This is a
single-threaded program." But that is not the behavior.
The "after" command, blocks all threads. In the Solaris/POSIX world,
sleep() blocks all threads and pthread_sleep() blocks only a the current
thread. I am looking for the Tcl equivalent.
Scott Redman wrote:
> I think you want this:
>
> after 5000 {set x 1}
> vwait x
That's the ticket! Thanks MUY MUCHO!
My main Tcl/Tk Reference doesn't mention "vwait". However, my little
O'Reilly Pocket Reference mentions it.
Thanks for pointing it out.
Does it work so cleanly ?
I mean, we all know the care that has to be taken when several event
sinks (like vwait) are started from different threads. Is the threading
part of 8.1 now so clean that all after/fileevents are properly demuxed
to their intended threads ? I'm not saying it's impossible; I'm just
asking for an official statement :).
Or did you mean *only from the main Tk thread* ?
In this case the caveat deserves a sticky one-line comment...
-Alex
That was absolutely not obvious from your post.
Specifically, in no place was it stated that you had really made use of
the '[test]thread create' command. Instead, you said you had
'discovered' something which is mistakenly identified as MT by newbies
fairly often (the fact that most callbacks yield so quickly that Tcl
spend 99% of its time awaiting events).
> The "after" command, blocks all threads. In the Solaris/POSIX world,
> sleep() blocks all threads and pthread_sleep() blocks only a the
> current thread. I am looking for the Tcl equivalent.
Why on earth didn't you give this crystal-clear, unambiguous statement
of your problem in the first place ;-) ?
That is interesting. Two options now:
1) Create a new flavour of the unary [after] that uses
pthread_sleep.
2) Silently modify the existing unary [after] so that it always
does so. There is not much existing MT Tcl code to worry
about anyway (esp. given the catastrophic effect of today's
[after] you just pointed out !), and for single-threaded apps
it would change nothing.
Reactions ?
-Alex
They are supposed to be.
-- Scott
This is something that should be posted to the scriptics bug database
IMHO, and it should be removed before 8.1 goes final.
http://www.scriptics.com/support/bugForm.html
--
Sincerely,
Andreas Kupries <a.ku...@westend.com>
<http://www.westend.com/~kupries/>
-------------------------------------------------------------------------------
Excellent ! Now what about Tk ? I understand that all threads can make
widget-modification calls, but is there more than one thread that can
vwait on GUI events ? If not, what happens if a side-thread calls a
modal dialog like tk_getOpenFile ? If yes, by what magic are the GUI
event demuxed ?
-Alex
In fact you can't ever interrupt a Tcl program (in a way it can
notice; preemption by other threads/processes on your system is OK)
except when that program asks if anything wishes to interrupt it.
This is at the (philosophical) heart of why an interpreter can never
have more than one thread running in it.
> If you can describe why it is you think you need to use after in such a
> manner, perhaps we can tell you a better way to accomplish the task. (if
> I were a betting man, I'd bet what you are interested in is vwait).
One thing that many people miss is that the [after] command has two
uses:
* Synchronous. Blocks the thread for the number of milliseconds
specified. e.g.
puts stderr "Hello"
after 2000
puts stderr "Goodbye"
exit
* Asynchronous. Schedules a piece of code for execution after a
number of milliseconds have passed. This code will only be
executed in an "interrupt" point, and when it runs it runs
uninterruptably in the same manner as ordinary Tcl code. You can
do some really neat stuff with this, including non-blocking
delays, (sort-of) continuations, and many other things I can't
think of at the moment. e.g.
after 2000 {set forever "has arrived"}
proc count n {puts $n; after 200 "count [incr n]"}
count 0
vwait forever
exit
Note that you can also prevent something scheduled with after from
happening if you have access to the after i.d. and this is useful
for some really quite sophisticated stuff. I don't feel like
doing a good example for it at the moment though... :^)
As you can see, understanding [after] is an interesting challenge.
Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>