Using Tcl with Pthreads
Total Page:16
File Type:pdf, Size:1020Kb
The following paper was originally published in the Proceedings of the Fifth Annual Tcl/Tk Workshop Boston, Massachusetts, July 1997 PtTcl: Using Tcl with Pthreads D. Richard Hipp Hwaci, Charlotte, NC Mike Cruse CTI, Ltd., Prescott, AZ For more information about USENIX Association contact: 1. Phone: 510 528-8649 2. FAX: 510 548-5738 3. Email: [email protected] 4. WWW URL: http://www.usenix.org PtTcl: Using Tcl with Pthreads D. Richard Hipp Mike Cruse Hwaci CTI, Ltd. 6200 Maple Cove Lane 1040 Whipple St. 225 Charlotte, NC 28269 Prescott, AZ 86301 Abstract This article describ es a new implementation of multi-threaded Tcl that is based on POSIX threads [Pthreads] and works with Tcl version 7.6. An upgrade to Tcl version 8.0 is planned. We call Tcl is not thread-safe. If two or more threads at- the package \PtTcl". PtTcl b orrows some of tempt to use Tcl at the same time, internal data Jankowski's ideas but is a completely new imple- structures can be corrupted and the program can mentation. crash. This is true even if the threads are using separate Tcl interpreters. PtTcl is a modi cation to the Tcl core that makes Tcl safe to use with POSIX threads. With PtTcl, 2 Threading Mo del each thread can create and use its own Tcl inter- preters that wil l not interfere with interpreters used The usual mo del for a multi-threaded program is in other threads. A message-passing mechanism al- that each thread has its own stack used to store lows Tcl interpreters running in di erent treads to subroutine return addresses and lo cal variables. communicate. However, even with PtTcl, the same In a compiled program, the hardware in co op era- interpreter stil l cannot beaccessed by more than one tion with the op erating system and thread library thread. take care of providing and managing these separate stacks. But in an interpreted language like Tcl, This paper describes the design, implementation and the interpreter must create and manage the sepa- use of PtTcl. rate stacks itself. The standard Tcl interpreter only makes provisions for a single stack. In order to make Tcl truly multi-threaded, it is necessary to change the Tcl core to allowmultiple stacks p er interpreter. 1 Intro duction Unfortunately, the concept of one stack per inter- preter is a fundamental assumption in the design of Tcl was originally designed for use in single- Tcl, and to change this assumption would require threaded programs only. But recently, there has a ma jor rewrite of manykey routines. In order to b een an increasing need to use the p ower of Tcl in avoid excessive rework of the Tcl core, wechose to applications that contain multiple threads of con- use a more restrictive thread mo del for PtTcl. trol. Unfortunately, the core Tcl library uses several static data structures that can b ecome corrupted if PtTcl allows an application to havemultiple Tcl in- accessed simultaneously bytwo or more threads. A terpreters running in indep endent threads, and each program crash is the usual result. thread in a PtTcl program can contain anynumber of interpreters including zero. But PtTcl only al- There is a least one prior e ort to make Tcl thread- lows an interpreter to b e run from a single thread. If safe. Steve Jankowski created a mo di ed version of another thread tries to use an interpreter, an error the Tcl sources called MTtcl [MtTcl] which allows message is returned. the use of Tcl in a multi-threaded environment. But Jankowski's implementation only works with Solaris In ordinary Tcl, there is a single event queue used threads and on Tcl versions 7.4 and earlier. to pro cess all timer and le events. In PtTcl, this used by PtTcl: concept is extended to one event queue p er thread. The fact that each thread has its own event queue is a necessary consequence of the restriction that Tcl A single thread can contain anynumb er of Tcl interpreters must always b e run in the same thread. interpreters. Recall that the usual action taken when an event ar- rives is for a Tcl script to run in resp onse. Supp ose A particular Tcl interpreter may only b e used an interpreter in thread A registers to receive an from within a single thread. event, but the event arrives while executing thread Each thread has its own event queue. B. There is no way for the receiving interpreter, run- ning in thread B, to execute the desired script b e- A message in the form of a Tcl script can b e cause that script can only be run from thread A. sent to the main Tcl interpreter in any thread. Hence, if we want to be able to invoke scripts in resp onse to events, each thread must have its own Tcl variables may be shared between two or event queue. more Tcl interpreters, even interpreters run- ning in separate threads. Each thread has the concept of a main interpreter. The main interpreter is di erent from other inter- preters in the same thread in only one way: you can send messages to the main interpreter. 3 New Tcl Commands Messages are a new kind of Tcl event, so a Tcl in- terpreter running in a given thread will not pro cess The PtTcl package implements two new Tcl com- any messages until it visits its event lo op. A Tcl in- mands. The \shared" command is used to desig- terpreter visits its event lo op whenever it executes nate variables that are to b e shared with other in- one of the standard Tcl commands vwait or update terpreters, and the \thread" command is used to or one of two commands added by PtTcl: thread create and control threads. eventloop and thread send. Messages can b e either synchronous meaning they 3.1 The \shared" command will wait for a resp onse or asynchronous re and forget. The result returned to the sending thread from a synchronous message is the result of the Tcl The shared is similar to the standard global com- script in the receiving thread or an error message if mand. Shared takes one or more arguments which the message could not b e sent for some reason. An are names of variables that are to be shared by asynchronous message has no result usually, but it all Tcl interpreters, including interpreters in other still might return an error if the message could not threads. Note that b oth interpreters must execute be sent. Asynchronous messages can b e broadcast the shared command indep endently b efore they will to all main interpreters or to all main interpreters really b e using the same variable. except the interpreter that is doing the sending. Unfortunately, the trace command will not work on A message can b e sent from anyinterpreter, not just shared variables. This is another consequence of the the main interpreter, or directly from C co de. There fact that an interpreter can only b e used in a single do es not have to b e a Tcl interpreter running in a thread. When a trace is set on a variable, a Tcl thread in order for that thread to send a message, script is run whenever that variable is read, written but a main interpreter is necessary for the message or deleted. But, if the trace was set by thread A to b e received. and the variable is changed by thread B, there is no way for thread B to invoke the trace script in thread Most variables used by a Tcl interpreter are private A. to that interpreter. But PtTcl implements a mech- anism for sharing selected variables b etween twoor more interpreters, even interpreters running in dif- 3.2 The \thread" command ferent threads. However, it is not p ossible to put trace events on shared variables, which limits their The thread command is more complex than usefulness. shared. Thread contains nine separate sub com- Here is a quick summary of the execution mo del mands used to create new threads, send and receive thread broadcast message messages, query the thread database, and so forth. [-sendtoself boolean] Each is describ ed separately b elow. The thread broadcast works like thread send ex- thread self cept that it sends the message to all threads and it always op erates asynchronously. Normally, it will Every thread in PtTcl that contains an interpreter is not send the message to itself, unless you also sp ec- assigned a unique p ositiveinteger Id. This Id is used ify the -sendtoself ag. by other thread commands to designate a message recipient or the target of a join. The thread self thread update command returns the Id of the thread that executes the command. This command causes the current thread to pro cess all p ending messages, that is, messages that other thread create [command] [-detach threads have sent and are waiting for this thread boolean] to pro cess. Only thread messages are pro cessed by this command { other kinds of p ending events are ig- New threads can be created using the thread nored. If you want to pro cess all p ending events in- create command. The optional argument to this cluding thread messages, use the update command command is a Tcl script that is executed by the new from regular Tcl. thread. After the sp eci ed script is completed, the new thread exits.