1Threads(3) Tcl Library Procedures Threads(3)
2
3
4
5______________________________________________________________________________
6
8 Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_Get‐
9 ThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_Cre‐
10 ateThread, Tcl_JoinThread - Tcl thread support
11
13 #include <tcl.h>
14
15 void
16 Tcl_ConditionNotify(condPtr)
17
18 void
19 Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
20
21 void
22 Tcl_ConditionFinalize(condPtr)
23
24 Void *
25 Tcl_GetThreadData(keyPtr, size)
26
27 void
28 Tcl_MutexLock(mutexPtr)
29
30 void
31 Tcl_MutexUnlock(mutexPtr)
32
33 void
34 Tcl_MutexFinalize(mutexPtr)
35
36 int
37 Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
38
39 int
40 Tcl_JoinThread(id, result)
41
43 Tcl_Condition *condPtr (in) A condition variable, which
44 must be associated with a mutex
45 lock.
46
47 Tcl_Mutex *mutexPtr (in) A mutex lock.
48
49 const Tcl_Time *timePtr (in) A time limit on the condition
50 wait. NULL to wait forever.
51 Note that a polling value of 0
52 seconds does not make much
53 sense.
54
55 Tcl_ThreadDataKey *keyPtr (in) This identifies a block of
56 thread local storage. The key
57 should be static and process-
58 wide, yet each thread will end
59 up associating a different
60 block of storage with this key.
61
62 int *size (in) The size of the thread local
63 storage block. This amount of
64 data is allocated and initial‐
65 ized to zero the first time
66 each thread calls Tcl_Get‐
67 ThreadData.
68
69 Tcl_ThreadId *idPtr (out) The referred storage will con‐
70 tain the id of the newly cre‐
71 ated thread as returned by the
72 operating system.
73
74 Tcl_ThreadId id (in) Id of the thread waited upon.
75
76 Tcl_ThreadCreateProc *proc (in) This procedure will act as the
77 main() of the newly created
78 thread. The specified client‐
79 Data will be its sole argument.
80
81 ClientData clientData (in) Arbitrary information. Passed
82 as sole argument to the proc.
83
84 int stackSize (in) The size of the stack given to
85 the new thread.
86
87 int flags (in) Bitmask containing flags allow‐
88 ing the caller to modify behav‐
89 ior of the new thread.
90
91 int *result (out) The referred storage is used to
92 place the exit code of the
93 thread waited upon into it.
94______________________________________________________________________________
95
97 Beginning with the 8.1 release, the Tcl core is thread safe, which
98 allows you to incorporate Tcl into multithreaded applications without
99 customizing the Tcl core. Starting with the 8.6 release, Tcl multi‐
100 threading support is on by default. To disable Tcl multithreading sup‐
101 port, you must include the --disable-threads option to configure when
102 you configure and compile your Tcl core.
103
104 An important constraint of the Tcl threads implementation is that only
105 the thread that created a Tcl interpreter can use that interpreter. In
106 other words, multiple threads can not access the same Tcl interpreter.
107 (However, a single thread can safely create and use multiple inter‐
108 preters.)
109
111 Tcl provides Tcl_CreateThread for creating threads. The caller can
112 determine the size of the stack given to the new thread and modify the
113 behavior through the supplied flags. The value TCL_THREAD_STACK_DEFAULT
114 for the stackSize indicates that the default size as specified by the
115 operating system is to be used for the new thread. As for the flags,
116 currently only the values TCL_THREAD_NOFLAGS and TCL_THREAD_JOINABLE
117 are defined. The first of them invokes the default behavior with no
118 special settings. Using the second value marks the new thread as join‐
119 able. This means that another thread can wait for the such marked
120 thread to exit and join it.
121
122 Restrictions: On some UNIX systems the pthread-library does not contain
123 the functionality to specify the stack size of a thread. The specified
124 value for the stack size is ignored on these systems. Windows cur‐
125 rently does not support joinable threads. This flag value is therefore
126 ignored on this platform.
127
128 Tcl provides the Tcl_ExitThread and Tcl_FinalizeThread functions for
129 terminating threads and invoking optional per-thread exit handlers.
130 See the Tcl_Exit page for more information on these procedures.
131
132 The Tcl_JoinThread function is provided to allow threads to wait upon
133 the exit of another thread, which must have been marked as joinable
134 through usage of the TCL_THREAD_JOINABLE-flag during its creation via
135 Tcl_CreateThread.
136
137 Trying to wait for the exit of a non-joinable thread or a thread which
138 is already waited upon will result in an error. Waiting for a joinable
139 thread which already exited is possible, the system will retain the
140 necessary information until after the call to Tcl_JoinThread. This
141 means that not calling Tcl_JoinThread for a joinable thread will cause
142 a memory leak.
143
144 The Tcl_GetThreadData call returns a pointer to a block of thread-pri‐
145 vate data. Its argument is a key that is shared by all threads and a
146 size for the block of storage. The storage is automatically allocated
147 and initialized to all zeros the first time each thread asks for it.
148 The storage is automatically deallocated by Tcl_FinalizeThread.
149
150 SYNCHRONIZATION AND COMMUNICATION
151 Tcl provides Tcl_ThreadQueueEvent and Tcl_ThreadAlert for handling
152 event queuing in multithreaded applications. See the Notifier manual
153 page for more information on these procedures.
154
155 A mutex is a lock that is used to serialize all threads through a piece
156 of code by calling Tcl_MutexLock and Tcl_MutexUnlock. If one thread
157 holds a mutex, any other thread calling Tcl_MutexLock will block until
158 Tcl_MutexUnlock is called. A mutex can be destroyed after its use by
159 calling Tcl_MutexFinalize. The result of locking a mutex twice from
160 the same thread is undefined. On some platforms it will result in a
161 deadlock. The Tcl_MutexLock, Tcl_MutexUnlock and Tcl_MutexFinalize
162 procedures are defined as empty macros if not compiling with threads
163 enabled. For declaration of mutexes the TCL_DECLARE_MUTEX macro should
164 be used. This macro assures correct mutex handling even when the core
165 is compiled without threads enabled.
166
167 A condition variable is used as a signaling mechanism: a thread can
168 lock a mutex and then wait on a condition variable with Tcl_Condition‐
169 Wait. This atomically releases the mutex lock and blocks the waiting
170 thread until another thread calls Tcl_ConditionNotify. The caller of
171 Tcl_ConditionNotify should have the associated mutex held by previously
172 calling Tcl_MutexLock, but this is not enforced. Notifying the condi‐
173 tion variable unblocks all threads waiting on the condition variable,
174 but they do not proceed until the mutex is released with Tcl_MutexUn‐
175 lock. The implementation of Tcl_ConditionWait automatically locks the
176 mutex before returning.
177
178 The caller of Tcl_ConditionWait should be prepared for spurious notifi‐
179 cations by calling Tcl_ConditionWait within a while loop that tests
180 some invariant.
181
182 A condition variable can be destroyed after its use by calling Tcl_Con‐
183 ditionFinalize.
184
185 The Tcl_ConditionNotify, Tcl_ConditionWait and Tcl_ConditionFinalize
186 procedures are defined as empty macros if not compiling with threads
187 enabled.
188
189 INITIALIZATION
190 All of these synchronization objects are self-initializing. They are
191 implemented as opaque pointers that should be NULL upon first use. The
192 mutexes and condition variables are either cleaned up by process exit
193 handlers (if living that long) or explicitly by calls to Tcl_MutexFi‐
194 nalize or Tcl_ConditionFinalize. Thread local storage is reclaimed
195 during Tcl_FinalizeThread.
196
198 Tcl provides no built-in commands for scripts to use to create, manage,
199 or join threads, nor any script-level access to mutex or condition
200 variables. It provides such facilities only via C interfaces, and
201 leaves it up to packages to expose these matters to the script level.
202 One such package is the Thread package.
203
205 To create a thread with portable code, its implementation function
206 should be declared as follows:
207
208 static Tcl_ThreadCreateProc MyThreadImplFunc;
209
210 It should then be defined like this example, which just counts up to a
211 given value and then finishes.
212
213 static Tcl_ThreadCreateType
214 MyThreadImplFunc(
215 ClientData clientData)
216 {
217 int i, limit = (int) clientData;
218 for (i=0 ; i<limit ; i++) {
219 /* doing nothing at all here */
220 }
221 TCL_THREAD_CREATE_RETURN;
222 }
223
224 To create the above thread, make it execute, and wait for it to finish,
225 we would do this:
226
227 int limit = 1000000000;
228 ClientData limitData = (void*)((intptr_t) limit);
229 Tcl_ThreadId id; /* holds identity of thread created */
230 int result;
231
232 if (Tcl_CreateThread(&id, MyThreadImplFunc, limitData,
233 TCL_THREAD_STACK_DEFAULT,
234 TCL_THREAD_JOINABLE) != TCL_OK) {
235 /* Thread did not create correctly */
236 return;
237 }
238 /* Do something else for a while here */
239 if (Tcl_JoinThread(id, &result) != TCL_OK) {
240 /* Thread did not finish properly */
241 return;
242 }
243 /* All cleaned up nicely */
244
246 Tcl_GetCurrentThread(3), Tcl_ThreadQueueEvent(3), Tcl_ThreadAlert(3),
247 Tcl_ExitThread(3), Tcl_FinalizeThread(3), Tcl_CreateThreadEx‐
248 itHandler(3), Tcl_DeleteThreadExitHandler(3), Thread
249
251 thread, mutex, condition variable, thread local storage
252
253
254
255Tcl 8.1 Threads(3)