TCL从TCL C线程和TCL脚本线程设置vwait变量

时间:2017-11-30 10:00:00

标签: tcl

我的C ++应用程序嵌入了TCL(8.6.7),需要同时通过Windows命名管道(dll)和TCP套接字(TCL脚本)获取数据。我想使用TCL线程通过管道和套接字实现同步数据采集。一个线程(threadPipe)通过TCL C api管理从命名管道读取数据,另一个线程通过TCL脚本(threadTclSocket)管理套接字。通过TCL脚本的主线程(C ++应用程序)启动数据采集,并在其TCL脚本中使用vwait forever等待(非阻塞)工作线程。

我的问题:

  • 如何通过TCL脚本(threadTclSocket)获取TCL C线程(threadPipe)和线程,以设置主应用程序的变量:forever 当它们完成以便主线程可以退出它的事件循环?
  • 我已阅读有关Tcl_ThreadQueueEventTcl_ThreadAlert的内容,但我不明白它们如何用于在主线程中设置变量forever

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

您应该使用twapi命名管道实现。我怀疑你的命名管道读取代码没有将其作为支持tcl fileevent异步API的通道。如果您有这样的支持,如twapi版本中所见,那么您根本不需要额外的线程。您可以简单地使用fileevent并在数据到达通道时调用一些tcl过程。

如果您继续使用现有代码,则使用Tcl_ThreadQueueEvent将事件发布到tcl通知程序,以便解释器线程在处理该事件时调用函数。这将控制转移到解释器线程。以下是我之前写过的一个例子:

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;
}

值得注意的是,我们有一个“继承”来自Tcl_Event的结构,并允许我们将自己的数据放入事件中。我们可以发布一些事件,并在完成后使用Tcl_ThreadAlert唤醒目标。目标函数(在本例中为EventProc)将传递给这个结构,但是将在解释器线程上运行,所以我们必须记住Tcl_Obj引用计数。

在您的情况下,您可能只想在事件过程中设置永久变量。

如果有用,您可以看到whole file

但是,您确定不应该在正确编写的命名管道通道上使用fileevent吗?

答案 1 :(得分:0)

感谢你的所有建议,我已经解决了我的问题。

使用TCL脚本设置forever vwait forever变量非常简单,只需使用forever作为thread::send的结果,并让主TCL线程等等。对于紧急在forever中的TCL C线程设置TCL_EventProc,挂起主TCL解释器。为了解决这个问题,我将forever的设置延迟了,直到事件循环空闲时使用after,如下所示:

after idle {set forever thread}