We are trying to develop TCL based application which allows to display and hide Qt GUI using tcl commands while mostly always providing user interaction through terminal.can simply call the notify function of this object , which will use queed blocking connection to notify gui (setState for example).
Coming from Qt world I also want the Gui to be responsive and that pushed me to solution having Qt and TCL in the different threads.
The task of starting Qt and Tcl was trivial. I created instance of QApplications,
And implemented run command in QThread subclass:
void BackendClient::run()
{
{
QMutexLocker locker(&mutex);
// Initialization of IGuiNotifier
....;
}
Tcl_Main(m_argc, m_argv, Tcl_AppInit);
}
But now I need to implement communication between the backend and gui threads.
1. The backend-> gui is relatively easy (or at least I think it is right now). I am planning to have implement IGuiNotifier interface which is going to be QObject subclass, make it available to the our base class Command implementation and each command
2. The gui - backend is unclear to me. Ideally it should be post message type communication, but I am not sure how to implement it.
Problem is in the fact that tcl thread runs its own the event loop right now.
So the only approach which comes to my mind is to inject in the loop mutex and use it as a guard to force tcl event loop to create and execute the command.
But https://www.tcl.tk/doc/howto/thread_model.html says "Tcl scripts in different threads can communicate by posting scripts onto the event queue of an interpreter in a different thread. This can be synchronous, where you wait for the result, orasynchronous, where your thread does not wait for the other thread to evaluate its script." Unfortunately I can't find example how to post that event, can it be done from non-tcl related thread?
Also since I am completely new to tcl is it viable solution? Is there better pattern?
On Friday, 1 October 2021 at 01:58:50 UTC+1, al...@flex-logix.com wrote:command can simply call the notify function of this object , which will use queed blocking connection to notify gui (setState for example).
We are trying to develop TCL based application which allows to display and hide Qt GUI using tcl commands while mostly always providing user interaction through terminal.
Coming from Qt world I also want the Gui to be responsive and that pushed me to solution having Qt and TCL in the different threads.
The task of starting Qt and Tcl was trivial. I created instance of QApplications,
And implemented run command in QThread subclass:
void BackendClient::run()
{
{
QMutexLocker locker(&mutex);
// Initialization of IGuiNotifier
....;
}
Tcl_Main(m_argc, m_argv, Tcl_AppInit);
}
But now I need to implement communication between the backend and gui threads.
1. The backend-> gui is relatively easy (or at least I think it is right now). I am planning to have implement IGuiNotifier interface which is going to be QObject subclass, make it available to the our base class Command implementation and each
to make sure that access to them on at least the Tcl side is non-blocking.)2. The gui - backend is unclear to me. Ideally it should be post message type communication, but I am not sure how to implement it.Providing you don't have to pass too much data about (you know your application much better than I do!) then you can use a pipe to pass messages from one thread to another. (You'd probably want a second pipe to send things in the other direction, and
Problem is in the fact that tcl thread runs its own the event loop right now.
So the only approach which comes to my mind is to inject in the loop mutex and use it as a guard to force tcl event loop to create and execute the command.
Pipes are pretty easy, and are supported by all common operating systems.and yet have things end up correctly in Tcl in another thread. (Assuming the Tcl thread is in the event loop.)
It's also possible to transfer other IO channels between threads, and the reflected channels of Tcl 8.5 are set up to hide the communication details. You could then use the basic Tcl IO C API straight from the Qt code without the complexity of pipes
asynchronous, where your thread does not wait for the other thread to evaluate its script." Unfortunately I can't find example how to post that event, can it be done from non-tcl related thread?But https://www.tcl.tk/doc/howto/thread_model.html says "Tcl scripts in different threads can communicate by posting scripts onto the event queue of an interpreter in a different thread. This can be synchronous, where you wait for the result, or
low level as well — at that level, messages are C structures allocated using the system memory allocator so that they can be allocated in one thread and freed in another — but the details are fairly complicated, especially for bidirectionalAlso since I am completely new to tcl is it viable solution? Is there better pattern?Otherwise, the easiest way to send messages is to have a little helper interpreter IN THE QT THREAD that does the details of the inter-thread communications (using the implementation provided in the thread package). Yes, you can do the messaging at the
You're quite likely going to end up with a small Tcl interpreter in the Qt thread. It doesn't really need to do all that much after things are set up.
Donal.
On Friday, October 1, 2021 at 9:28:49 AM UTC-7, Donal K. Fellows wrote:command can simply call the notify function of this object , which will use queed blocking connection to notify gui (setState for example).
On Friday, 1 October 2021 at 01:58:50 UTC+1, al...@flex-logix.com wrote:
We are trying to develop TCL based application which allows to display and hide Qt GUI using tcl commands while mostly always providing user interaction through terminal.
Coming from Qt world I also want the Gui to be responsive and that pushed me to solution having Qt and TCL in the different threads.
The task of starting Qt and Tcl was trivial. I created instance of QApplications,
And implemented run command in QThread subclass:
void BackendClient::run()
{
{
QMutexLocker locker(&mutex);
// Initialization of IGuiNotifier
....;
}
Tcl_Main(m_argc, m_argv, Tcl_AppInit);
}
But now I need to implement communication between the backend and gui threads.
1. The backend-> gui is relatively easy (or at least I think it is right now). I am planning to have implement IGuiNotifier interface which is going to be QObject subclass, make it available to the our base class Command implementation and each
to make sure that access to them on at least the Tcl side is non-blocking.)2. The gui - backend is unclear to me. Ideally it should be post message type communication, but I am not sure how to implement it.Providing you don't have to pass too much data about (you know your application much better than I do!) then you can use a pipe to pass messages from one thread to another. (You'd probably want a second pipe to send things in the other direction, and
Problem is in the fact that tcl thread runs its own the event loop right now.
So the only approach which comes to my mind is to inject in the loop mutex and use it as a guard to force tcl event loop to create and execute the command.
and yet have things end up correctly in Tcl in another thread. (Assuming the Tcl thread is in the event loop.)Pipes are pretty easy, and are supported by all common operating systems.
It's also possible to transfer other IO channels between threads, and the reflected channels of Tcl 8.5 are set up to hide the communication details. You could then use the basic Tcl IO C API straight from the Qt code without the complexity of pipes
asynchronous, where your thread does not wait for the other thread to evaluate its script." Unfortunately I can't find example how to post that event, can it be done from non-tcl related thread?But https://www.tcl.tk/doc/howto/thread_model.html says "Tcl scripts in different threads can communicate by posting scripts onto the event queue of an interpreter in a different thread. This can be synchronous, where you wait for the result, or
the low level as well — at that level, messages are C structures allocated using the system memory allocator so that they can be allocated in one thread and freed in another — but the details are fairly complicated, especially for bidirectionalAlso since I am completely new to tcl is it viable solution? Is there better pattern?Otherwise, the easiest way to send messages is to have a little helper interpreter IN THE QT THREAD that does the details of the inter-thread communications (using the implementation provided in the thread package). Yes, you can do the messaging at
You're quite likely going to end up with a small Tcl interpreter in the Qt thread. It doesn't really need to do all that much after things are set up.
Donal.If you do want to pursue having a Tcl interpreter in the Qt thread, seriously consider this:
https://ssl.webpack.de/www.eurotcl.eu/presentations/EuroTcl2019-Griffin-TclQtEventLoop.pdf
(from EuroTcl 2019: https://ssl.webpack.de/www.eurotcl.eu/pastevents.html#eurotcl2019)
-Brian
especially for bidirectional communications.Yes, you can do the messaging at the low level as well — at that level, messages are C structures allocated using the system memory allocator so that they can be allocated in one thread and freed in another — but the details are fairly complicated,
Pipes are pretty easy, and are supported by all common operating systems.
and yet have things end up correctly in Tcl in another thread. (Assuming the Tcl thread is in the event loop.)It's also possible to transfer other IO channels between threads, and the reflected channels of Tcl 8.5 are set up to hide the communication details. You could then use the basic Tcl IO C API straight from the Qt code without the complexity of pipes
Otherwise, the easiest way to send messages is to have a little helper interpreter IN THE QT THREAD that does the details of the inter-thread communications (using the implementation provided in the thread package).
On Friday, October 1, 2021 at 1:34:16 PM UTC-7, briang wrote:command can simply call the notify function of this object , which will use queed blocking connection to notify gui (setState for example).
On Friday, October 1, 2021 at 9:28:49 AM UTC-7, Donal K. Fellows wrote:
On Friday, 1 October 2021 at 01:58:50 UTC+1, al...@flex-logix.com wrote:
We are trying to develop TCL based application which allows to display and hide Qt GUI using tcl commands while mostly always providing user interaction through terminal.
Coming from Qt world I also want the Gui to be responsive and that pushed me to solution having Qt and TCL in the different threads.
The task of starting Qt and Tcl was trivial. I created instance of QApplications,
And implemented run command in QThread subclass:
void BackendClient::run()
{
{
QMutexLocker locker(&mutex);
// Initialization of IGuiNotifier
....;
}
Tcl_Main(m_argc, m_argv, Tcl_AppInit);
}
But now I need to implement communication between the backend and gui threads.
1. The backend-> gui is relatively easy (or at least I think it is right now). I am planning to have implement IGuiNotifier interface which is going to be QObject subclass, make it available to the our base class Command implementation and each
and to make sure that access to them on at least the Tcl side is non-blocking.)2. The gui - backend is unclear to me. Ideally it should be post message type communication, but I am not sure how to implement it.Providing you don't have to pass too much data about (you know your application much better than I do!) then you can use a pipe to pass messages from one thread to another. (You'd probably want a second pipe to send things in the other direction,
Problem is in the fact that tcl thread runs its own the event loop right now.
So the only approach which comes to my mind is to inject in the loop mutex and use it as a guard to force tcl event loop to create and execute the command.
pipes and yet have things end up correctly in Tcl in another thread. (Assuming the Tcl thread is in the event loop.)Pipes are pretty easy, and are supported by all common operating systems.
It's also possible to transfer other IO channels between threads, and the reflected channels of Tcl 8.5 are set up to hide the communication details. You could then use the basic Tcl IO C API straight from the Qt code without the complexity of
asynchronous, where your thread does not wait for the other thread to evaluate its script." Unfortunately I can't find example how to post that event, can it be done from non-tcl related thread?But https://www.tcl.tk/doc/howto/thread_model.html says "Tcl scripts in different threads can communicate by posting scripts onto the event queue of an interpreter in a different thread. This can be synchronous, where you wait for the result, or
the low level as well — at that level, messages are C structures allocated using the system memory allocator so that they can be allocated in one thread and freed in another — but the details are fairly complicated, especially for bidirectionalAlso since I am completely new to tcl is it viable solution? Is there better pattern?Otherwise, the easiest way to send messages is to have a little helper interpreter IN THE QT THREAD that does the details of the inter-thread communications (using the implementation provided in the thread package). Yes, you can do the messaging at
complicated, especially for bidirectional communications.You're quite likely going to end up with a small Tcl interpreter in the Qt thread. It doesn't really need to do all that much after things are set up.
Donal.If you do want to pursue having a Tcl interpreter in the Qt thread, seriously consider this:
https://ssl.webpack.de/www.eurotcl.eu/presentations/EuroTcl2019-Griffin-TclQtEventLoop.pdf
(from EuroTcl 2019: https://ssl.webpack.de/www.eurotcl.eu/pastevents.html#eurotcl2019)
-BrianAlex (Oleksandr) Malyushytskyy
8:41 PM (19 minutes ago)
to comp.lang.tcl
Thanks Donal and Brian for input,
Yes, you can do the messaging at the low level as well — at that level, messages are C structures allocated using the system memory allocator so that they can be allocated in one thread and freed in another — but the details are fairly
I was going to implement the backend->gui communication using Qt utilities - signals and slots with queued connections. This is partially done already so the backend gets a Qt object subclass pointer which implements the custom interface every commandshould when changing UI related data.
I could also use the same mechanism for TCL-> gui communication, but for that I need to run the Qt event loop in the thread I call TCL_MAIN.
That gets a bit complicated since this is not even the QT main thread.
I would not throw away the idea of posting message and would greatly appreciate examples for creating and sending messages with C API.
stop reading from the pipe even though nothing is sent most of the time.Pipes are pretty easy, and are supported by all common operating systems. I have to say I had no much experience with pipes, but as far as I know there is no cross-platform implementation and what is more important using pipes will require the call to read from pipe in the event loop and event loop basically will have to non-
I might be wrong, but if I am right, I see no advantages using pipe over adding mutex in TCL standard event loop and just add the list of strings/commands gui wants the main loop to execute (before processing the other events)
and yet have things end up correctly in Tcl in another thread. (Assuming the Tcl thread is in the event loop.)It's also possible to transfer other IO channels between threads, and the reflected channels of Tcl 8.5 are set up to hide the communication details. You could then use the basic Tcl IO C API straight from the Qt code without the complexity of pipes
I have to admit I fail to understand how redirection/reflected channels can help me to pass the data from Qt/Gui thread to TCL. (Basically gui should pass strings to TCL ). But I failed to find a C API example using the feature, and do not think Iunderstand it completely, so I will try to look at it tomorrow.
1. You are mentioning a helper interpreter IN THE QT THREAD, but how to have the interpreter help me to communicate?Otherwise, the easiest way to send messages is to have a little helper interpreter IN THE QT THREAD that does the details of the inter-thread communications (using the implementation provided in the thread package).
2. Does having an interpreter in the main thread means that QT EVENT LOOP will have to be merged (like Brian says?)
2.It seems that the recommendation is using TCL in 2 threads. Main thread is gui thread , tcl is used there solely for communication, the second one will be for user input/output in the terminal (no Qt), It also will execute all the tcl commands.
But I can't find an example on how to use "the implementation provided in the thread package" on a C api level, is there anything available I am missing?
Thanks and best regards!
Alex
For any GUI application, the event loop is critical, independent of the presence of threads. Integrate the event loop, then just use Tcl as you would any other C function.I'm not sure. I suspect that assuming Threads are required in order to integrate Tcl into a Qt application is misguided. Threads are often used in places that aren't necessary.
application, create a Tcl interpreter, and initialize it according to the needs of your Qt application. This is different from calling Tcl_Main(), because Tcl_Main() basically assumes "ownership" of everything. Once you have the interpreter, you canI think it's a mistake to call Tcl_Main() from within a Qt program. You have to decide if this is a Qt application or a Tcl application. Choose one, then use the other toolkit as a dependent subsystem. What does this mean? In the case of a Qt
I think it's a mistake to call Tcl_Main() from within a Qt program.
Thanks Bryan,application, create a Tcl interpreter, and initialize it according to the needs of your Qt application. This is different from calling Tcl_Main(), because Tcl_Main() basically assumes "ownership" of everything. Once you have the interpreter, you can call
For any GUI application, the event loop is critical, independent of the presence of threads. Integrate the event loop, then just use Tcl as you would any other C function.I'm not sure. I suspect that assuming Threads are required in order to integrate Tcl into a Qt application is misguided. Threads are often used in places that aren't necessary.
Using threads are inspired not by the need of integration.
The backend will run long time processing tasks.
Having such tasks in the thread is the only real option to keep gui responsive.
The only alternative of periodically from the code process events causing a lot of issues, is not reliable and impossible to implement without putting a ton of calls into unrelated code.
The thread is a need , not a desire,
I think it's a mistake to call Tcl_Main() from within a Qt program. You have to decide if this is a Qt application or a Tcl application. Choose one, then use the other toolkit as a dependent subsystem. What does this mean? In the case of a Qt
For our application in a regular workflow GUI is an important , but a "secondary" function.
Users may choose to show it or not from tcl.
In fact it has to run on Linux without X present and the user may not be able to start gui.
So it is natural to say that TCL should be the main.
But if we want to show gui and immediately face the problem: QWidgets have to be in the main thread.
So if the system is capable of showing gui, we need to put Qt in the main thread.
Do we want tcl in the same with GUI thread? No, because 90% of the commands are long running.
Do you see any specific problem?I think it's a mistake to call Tcl_Main() from within a Qt program.
As far as I understand there are only 3 problems to solve:
1. Make tcl and Qt run in different threads (done)
2. TCL to GUI notifications ( see no problem)
Backend has a pointer to interface and QObject class implementing it sends signals connected with queued blocking connection.
So every command calling it will wait for gui to process it.
3. Gui to tcl notifications (this is what I try to solve now):
Gui has to post the text commands to the tcl thread.
Gui accesses the data to be shown through implemented by the backend interface.
Access to such data is controlled by the state of the document,
which every tcl command changing the state should set, but there is no knowledge about tcl in the gui and vice versa.
Do you see any pitfalls in such a design?
Otherwise why is it a mistake?
Best regards,
Alex
For our application in a regular workflow GUI is an important , but a "secondary" function.
Users may choose to show it or not from tcl.
In fact it has to run on Linux without X present and the user may not be
able to start gui.
So it is natural to say that TCL should be the main.
But if we want to show gui and immediately face the problem: QWidgets
have to be in the main thread.
So if the system is capable of showing gui, we need to put Qt in the main thread.
Do we want tcl in the same with GUI thread? No, because 90% of the
commands are long running.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 285 |
Nodes: | 16 (2 / 14) |
Uptime: | 69:37:50 |
Calls: | 6,488 |
Calls today: | 1 |
Files: | 12,096 |
Messages: | 5,275,482 |