[ Team LiB ] Previous Section Next Section

Preserving and Releasing Threads

A thread created with a script not containing a thread::wait command terminates as soon as the script finishes executing. But if a thread enters its event loop, it continues to run until its event loop terminates. So how do you terminate a thread's event loop?

Each thread maintains an internal reference count. The reference count is set initially to 0, or to 1 if you create the thread with the thread::create -preserved option. Any thread can increment the reference count afterwards by executing thread::preserve, and decrement the reference count by executing thread::release. These commands affect the reference count of the current thread unless you specify the ID of another thread. If a call to thread::release results in a reference count of 0 or less, the thread is marked for termination.

The use of thread reference counts allows multiple threads to preserve the existence of a worker thread until all of the threads release the worker thread. But the majority of multi-threaded Tcl applications don't require that degree of thread management. In most cases, you can simply create a thread and then later use thread::release to terminate it:

set worker [thread::create]
thread::send -async $worker $script
# Later in the program, terminate the worker thread
thread::release $worker

A thread marked for termination accepts no further messages and discards any pending events. It finishes processing any message it might be executing currently, then exits its event loop. If the thread entered its event loop through a call to thread::wait, any other commands following thread::wait are executed before thread termination, as shown in Example 21-7. This can be useful for performing "clean up" tasks before terminating a thread.

Example 21-7 Executing commands after thread::wait returns
set t [thread::create {
    puts "Starting worker thread"
    thread::wait
    # This is executed after the thread is released
    puts "Exiting worker thread"
}]

Note that if a thread is executing a message script when thread::release is called (either by itself or another thread), the thread finishes executing its message script before terminating. So, if a thread is stuck in an endless loop, calling thread::release has no effect on the thread. In fact, there is no way to kill such a "runaway thread."

graphics/common_icon.gif

Always use thread::wait to enter a thread's event loop.


This system for preserving and releasing threads works only if you use the thread::wait command to enter the thread's event loop (or if you did not provide a creation script when creating the thread). If you use vwait or tkwait to enter the event loop, thread::release cannot terminate the thread.

    [ Team LiB ] Previous Section Next Section