• Sending message/wake up tcl thread from foreign thread

    From Alex (Oleksandr) Malyushytskyy@21:1/5 to All on Fri Oct 8 13:32:01 2021
    I run tcl Tcl_MainEx from the QThread . Main thread is used to display Qt gui (it has to be in the main thread).

    void BackendClient::run()
    { // this runs in tcl thread
    {
    QMutexLocker locker(&mutex);
    bIni(m_argc, m_argv);
    eflx::app::Manager::Init(m_argc, nullptr);

    auto id = Tcl_GetCurrentThread();
    m_tclThreadId = id;

    Qt::HANDLE hndl = currentThreadId();
    m_Tcl_Interp = (Tcl_CreateInterp)();

    qDebug() << "run(): id " << id << " hndl == " << hndl << "\n%";
    }

    Tcl_MainEx(m_argc, m_argv, Tcl_AppInit, m_Tcl_Interp);
    }

    TCL itself runs as well as Qt gui.
    I am trying to post messages from qt gui thread to tcl thread similar to example from tclThreadTest
    The below function should have result in ThreadEventProc call.
    And even though Tcl_ThreadQueueEvent and Tcl_ThreadAlert under debugger seems run just fine, I do not see qany command executed in TCL terminal.


    void BackendClient::sendTclCommand(const QString scriptStr)
    {
    QMutexLocker locker(&mutex);
    {
    if (!BackendClient::m_Qt_Interp)
    {
    BackendClient::m_Qt_Interp = (Tcl_CreateInterp)();
    }

    // Create the event for its event queue.
    ThreadEvent* threadEventPtr = nullptr;
    threadEventPtr = (ThreadEvent*)ckalloc(sizeof(ThreadEvent));

    std::string str = scriptStr.toStdString();
    threadEventPtr->script = (char*)ckalloc(str.length() + 1);
    strcpy(threadEventPtr->script, str.c_str());
    threadEventPtr->resultPtr = NULL;

    threadEventPtr->event.proc = ThreadEventProc;
    Tcl_ThreadQueueEvent(m_tclThreadId, (Tcl_Event*)threadEventPtr,
    TCL_QUEUE_TAIL);
    Tcl_ThreadAlert(m_tclThreadId);
    }
    }

    Do I miss something obvious? Anybody could give me some pointers please?

    Best regards,
    Alex

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Werner@21:1/5 to All on Fri Oct 8 14:00:11 2021
    Alex,

    where's your event loop in the Tcl thread? You should have something like "vwait forever" at least.

    HTH,
    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alex (Oleksandr) Malyushytskyy@21:1/5 to Christian Werner on Fri Oct 8 14:41:22 2021
    On Friday, October 8, 2021 at 2:00:13 PM UTC-7, Christian Werner wrote:
    Alex,

    where's your event loop in the Tcl thread? You should have something like "vwait forever" at least.

    HTH,
    Christian

    Tcl_MainEx(m_argc, m_argv, Tcl_AppInit, m_Tcl_Interp); has an infinite loop which waits on length = Tcl_GetsObj(is.input, is.commandPtr); in tclMain

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Werner@21:1/5 to All on Fri Oct 8 14:46:09 2021
    Tcl_MainEx(m_argc, m_argv, Tcl_AppInit, m_Tcl_Interp); has an infinite loop which waits on length = Tcl_GetsObj(is.input, is.commandPtr); in tclMain

    which is not an event loop but blocking in a channel read operation, isn't it? So how shall an event be handled then?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alex (Oleksandr) Malyushytskyy@21:1/5 to Christian Werner on Fri Oct 8 15:09:42 2021
    On Friday, October 8, 2021 at 2:46:11 PM UTC-7, Christian Werner wrote:
    Tcl_MainEx(m_argc, m_argv, Tcl_AppInit, m_Tcl_Interp); has an infinite loop which waits on length = Tcl_GetsObj(is.input, is.commandPtr); in tclMain
    which is not an event loop but blocking in a channel read operation, isn't it? So how shall an event be handled then?

    So how the threads are created in the tcl script when run from blocking in a channel read operations i tclsh.exe (? Where is the event loop started in this case?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Werner@21:1/5 to All on Fri Oct 8 15:27:42 2021
    So how the threads are created in the tcl script when run from blocking in a channel read operations i tclsh.exe (? Where is the event loop started in this case?

    Assuming, that you're executing a script which does some thread creation at the end you'll have to do a "vwait forever", otherwise your main script terminates.

    In your situation, you could read a little script containing "vwait forever" from is.input in order to have your event loop.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alex (Oleksandr) Malyushytskyy@21:1/5 to Christian Werner on Fri Oct 8 16:26:42 2021
    On Friday, October 8, 2021 at 3:27:44 PM UTC-7, Christian Werner wrote:
    So how the threads are created in the tcl script when run from blocking in a channel read operations i tclsh.exe (? Where is the event loop started in this case?
    Assuming, that you're executing a script which does some thread creation at the end you'll have to do a "vwait forever", otherwise your main script terminates.

    In your situation, you could read a little script containing "vwait forever" from is.input in order to have your event loop.

    Christian ,

    Thanks, for help. I was confused about how tcl loop works.

    I am not sure your suggestion would work for me, since "vwait forever" would disable the user input in the terminal.
    Let me try to explain what I try to achieve.
    Even though I am forced to start TCL in the secondary thread , it is just to fight the inability of Qt to run widgets in the secondary thread.
    But most likely our application will ever have 2 threads. TCl Loop is created from QT as soon application starts, but QT (primary application thread ) will basically do nothing else unless "show_gui" command is executed.
    All the tcl commands should be executed in the single tcl thread in the blocking manner ( if command is long running - it creates threads as needed , but they are not controlled from tcl)
    Since tcl is how application is started and GUI might not be even shown we want the terminal code behave exactly the same way as with tclsh.exe.

    So I am trying to use original Tcl_MainEx.
    And the only problem I still can't solve - how to pass script from Qt to Tcl. (Tcl to Qt communication will be synchronized when commands are executed using Qt mechanics)

    As far as I understand I have 2 option:
    1. set custom TclGetMainLoop procedure which will wait for either text typed by user in the terminal or receive text from ui.
    2. write my own stream (basically std::in with the ability to write to it) and set it as an input channel.

    Hope this makes sense.
    And thanks again,

    Alex

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)