You should probably use the twapi named pipe implementation. I suspect your named pipe reading code is not presenting this as a channel that supports the tcl fileevent asynchronous API. If you had such support, as is found in the twapi version, then you don't need the additional thread at all. You simpley use fileevent and have some tcl procedure called when data arrives on the channel.
If you persist with the existing code then you use Tcl_ThreadQueueEvent to post an event to the tcl notifier so that the interpreter thread will then call a function when it processes that event. This shifts control to the interpreter thread. Here is an example from something I wrote previously:
static void MailslotSignalledProc(void *clientData)
{
MailslotData *slotPtr = (MailslotData *)clientData;
MailslotEvent *evPtr = NULL;
DWORD cbRead, cbSize = 0, cQueued = 0;
BOOL br = FALSE;
Tcl_GetLongFromObj(NULL, slotPtr->sizeObj, &cbSize);
GetOverlappedResult(slotPtr->handle, &slotPtr->ov, &cbRead, FALSE);
do
{
evPtr = (MailslotEvent *)ckalloc(sizeof(MailslotEvent));
evPtr->header.proc = EventProc;
evPtr->header.nextPtr = NULL;
evPtr->interp = slotPtr->pkgPtr->interp;
Tcl_Preserve(evPtr->interp);
evPtr->slotPtr = slotPtr;
evPtr->messageObj = Tcl_NewByteArrayObj(slotPtr->message, cbRead);
Tcl_IncrRefCount(evPtr->messageObj);
Tcl_ThreadQueueEvent(slotPtr->wait.tid, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
/*
* Schedule another read on the mailslot. This may return
* immediately if data is already available. We also rate-limit
* by enforcing a wait after 64 immediate messages.
*/
br = ReadFile(slotPtr->handle, slotPtr->message, cbSize, &cbRead, &slotPtr->ov);
++cQueued;
} while (br && cQueued < 64);
Tcl_ThreadAlert(slotPtr->wait.tid);
return;
}
Of note is we have a structure that 'inherits' from Tcl_Event and allows us to put our own data in the event. We can post a number of events and use Tcl_ThreadAlert to wake up the target once we are done. The target function (EventProc in this case) will be passed this structure but will be running on the interpreter thread, so we have to mind the Tcl_Obj reference counting.
In your case it sounds like you may just wish to set the forever variable in your event procecdure.
If its useful you can see the whole file.
However, are you sure you shouldn't just use fileevent on a properly written named pipe channel?
while {$waitcount < 2} {vwait waitcount}and increasing the variablewaitcountwhen the other threads are finished.waitcountand return control to the main TCL interpreter. It seems to hang after set I the variable in theTCL_EventProc.Tcl_ThreadQueueEventto queue an event in the main thread that usesTcl_Evalwithincr ::waitcount.