See Also edit
- notifier
- The bridge between the world of events and the rest of the event loop.
- thread
- The next step after one reaches the limits of the the Tcl event loop.
Description edit
Tcl/Tk's event loop is essentially single threaded. There is a main event loop, Tcl_DoOneEvent(), that checks for work to do and handles that work by making callbacks. These callbacks are registered with the event loop by after, fileevent, and bind, by -command, -xscrollcommand, and similar options on widgets, and by various things within C code.Main Event ----+----> Callback from Tcl_DoWhenIdle (after idle) Loop | +----> Callback from Tcl_CreateTimerHandler (after N) | +----> Callback from Tcl_CreateChannelHandler (fileevent) | +----> Callback from Tk_CreateEventHandler | (bind, -command, etc) | +----> Other callbacks (Tk_CreateGenericHandler, Tk_CreateErrorHandler, etc.)The natural flow of the event loop is something like:
Start | |<----------------------------------------------------------+ v ^ Do I have No[*] Calculate how Sleep for at | work to do? -----> long I may sleep -----> most that much --->| | time | | Yes | | | v | Do one callback | | | +-----------------------------------------------------------+ [*] This may cause a return from the event loop if it was invoked recursively (see below)Commands like update, tkwait, and vwait give the illusion of multithreading because they cause more events to be processed. It is just an illusion. What they really do is to invoke the event loop recursively:
Main Main More event ---> Callback ---> update ---> event ---> callbacks loop loop as neededwith different termination conditions:
- update
- Enters the event loop and services both queues in the normal manner until all events remaining in the main queue are scheduled in the future and the idle queue is empty.
- update idletasks
- Enters the event loop and services the idle queue until its empty. Events are queued on the idle queue by after idle and Tcl_DoWhenIdle.
- vwait
- Enters the event loop and services both queues in the normal manner until the specified variable is modified.
- tkwait
- Enters the event loop and services both queues in the normal manner until various more complex conditions are met.
DKF: Tcl doesn't run the event loop by default, so idiomatically people do this in their pure Tcl scripts to start the event loop:
vwait foreverTk does run an event loop by default (and it handles the interactive console on Unix by fileevent — well, strictly the C API equivalent — so it looks the same as the blocking Tcl interactive console). The termination condition for the Tk event loop is having all main windows of the application closed; each interpreter that has loaded the Tk package has to destroy its root toplevel widget.
garynkill: Hi i very new to Tcl/Tk. I need to do a simulation and wondering how to do i create multi-threading environment - as i have a skim through the "man" pages and discover there weren't any threads commands. And found out about events. How to do i go about coding where i need a timer running and after every 10s call a "command" to be run? - RS: It is possible to build Tcl with multiple threads, and in the future this may even become standard. However, threads can make debugging much more difficult, and with the event model, it's easy to implement timers and repeated scheduled events:
proc every {ms body} { eval $body; after $ms [info level 0] } every 10000 {puts "hello world"}See the every page for more.garynkill: Thanks a lot for your help! Just an equiry it is possible to make use of only event and create a simulation program for example a simulation like running 10 nodes each operating as one thread and sending each messages to one another. I know how to do it in threads in Java but i am still a newbie to Tcl/tk so asking whether it is possible to use events to do this or if you have any links to these related tutorials? It would be most helpful! Thanks againyes, it is possible, and probably significantly easier to do with events than with threads. I don't know of any tutorials but the problem sounds fairly trivial. Use 'event generate' to send messages (assuming a "node" is represented as a widget) and 'bind' to have each node respond to the message. Use tcl/tk 8.5 so you can make use of the -data option of 'event generate'. garynkill: Thanks a lot :)garynkill: Can somebody give me a rough example how event works within Tcl context or TK context where it can be implemented. Still had no heads over it. Thanks. Sorry a newbieUS: 'event generate' is a Tk command. For the purpose you mentioned above use after 0 handlerproc. This schedules your task for immediate execution (as soon as Tcl has nothing else to do).garynkill: Then how about if i want a procedure to execute every 10 s like this can it be done by this command.US: after 10000 handlerproc (Take a look at every).garynkill: How do you stop cancel events in the events loop?lexfiend: Using after cancel, of course.
[GMGJunior] 2016-01-03 09:53:33:I have a question: how the event loop is synchronized with threads?Example: 1. The Main Thread is in event loop by Tk - some GUI handling messages. Let's say this GUI works with some array "ThreadsInfo":
set ThreadID [ thread::create ] set ThreadsInfo($ThreadID,status) "Running" set status $ThreadsInfo($ThreadID,status) thread::wait By using GUI the ThreadsInfo array is constantly changed.2. Now, some thread with ThreadID sends a code to the main thread, which modifies the ThreadsInfo array.
thread::send $MainThreadID \ { set status $ThreadsInfo([ thread::id ],"Error") }I understand, that this case requires tsv::set/get operations and I know how it works.My question is: when the code is accepted by the Main Thread, is it performed atomically? Or could this Threads Info be changed by GUI during the execution of the code sent inside the thread::send?Thanks.chw: as far as I've understood Tcl you should stop worrying and learn to love the event loop and the apartment threading model. Things delivered by other threads are somewhat like an event and thus handled synchronously, i.e. there's never any unexpected interruption of the control flow. Java is more low level in this regard. There you have to deal with concurrency by using explicit synchronization points on objects and/or object methods. OTOH, Java gives you direct means to deal with waiting and wake up on entities with synchronization capabilities.