Tcl interpreter objects internally use thread-specific data extensively in order to avoid most global locks. This goes as far as including thread-specific memory management pools, at least for common allocations, and Tcl code is executed as part of initialising the interpreter state, so it's really not possible to use an interpreter in a different thread from the one in which it was created. The Tcl library checks that you're using it correctly in a few places, at least in some build modes, and will make the process abort()
(or Windows's equivalent) if you disobey the rules; that's much friendlier than the crash that would otherwise be coming due to fundamental assumptions not being respected…
This means that you must create, use, and destroy the interpreter on the same thread.
You might be advised to initialise the Tcl interpreter lazily if you can't guarantee that the containing object is used in the same thread that it was created in. You might think that this results in handling of things that isn't really the C++ way, but the thread-bound nature of interpreters means that you've really not got any alternative. (You might want to look at Tcl_CreateExitHandler()
for help with cleaning up the interpreter when the thread goes away, but that will only help if Tcl_FinalizeThread()
or Tcl_ExitThread()
are called; if you're being thread-promiscuous on the C++ side then there's a good chance that you'll be baking in all sorts of problems anyway.)
If the C++ part insists on using multiple threads, you'll have to have a single thread for the Tcl code and use inter-thread messaging to let the other threads tell it things. That's done with Tcl_ThreadQueueEvent()
. The canonical way to use that is the thread package, and that includes the canonical example of how to do so (github.com/tcltk/thread/generic/threadCmd.c); most of the complexity in there relates to turning an essentially one-way (but “reliable”) operation into a two-way one that lets you do a procedure call into a different thread; one-way calls are far simpler.