Home » U++ Library support » U++ MT-multithreading and servers » How do I create a loop for a window to react to volatile changes to a global variable?
How do I create a loop for a window to react to volatile changes to a global variable? [message #51334] |
Mon, 11 March 2019 09:49  |
slashupp
Messages: 231 Registered: July 2009
|
Experienced Member |
|
|
The problem:
I have some global variables get&set by detached threads, using mutexes when getting and setting them.
I have a window that need to update it's display based on changes in the variables, also using the mutexes to get & set the values.
The changes are volatile/random/unpredictable ...
What I tried:
I passed a pointer to the window to the threads when I create them, and use the pointer to call methods
in the window to do the updates
Result: the app crashes with:
"... Using GUI in non-main thread without GuiLock"
I added "GuiLock __;" in the methods but then get:
"Assertion failed in ..../CtrlCore/GtkCapture.cpp, line 41 IsMainThread()"
(I know that this same code did work with an older release of Upp, but is now broken)
Any ideas on how I can fix this would be much appreciated.
|
|
|
Re: How do I create a loop for a window to react to volatile changes to a global variable? [message #51335 is a reply to message #51334] |
Mon, 11 March 2019 12:44   |
Oblivion
Messages: 1206 Registered: August 2007
|
Senior Contributor |
|
|
Hello slashupp,
If you are calling a method of the main window (main thread), then add a GuiLock "in" that method, it is better that way.
E.g.:
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
class ThreadTest : public TopWindow {
Button start;
ArrayCtrl array;
public:
ThreadTest()
{
SetRect(0, 0, 800, 600);
CenterScreen();
array.AddColumn("Number");
Add(array.HSizePos().VSizePos(0, 30));
Add(start.SetLabel("Start Thread").RightPos(2, 120).BottomPos(2, 26));
start << [=] { RunThread(); };
}
void RunThread()
{
Thread t;
t.Run([=]{
for(int i = 1; i < 30000; i++) {
// GuiLock __;
SetArray(i);
}
});
t.Detach();
}
void SetArray(int n)
{
GuiLock __;
array.Add(n);
if(n == 10) { // Resize window from within thread...
SetRect(0, 0, 640, 480);
}
}
};
GUI_APP_MAIN
{
ThreadTest().Run();
}
Also,
Quote:
I added "GuiLock __;" in the methods but then get:
"Assertion failed in ..../CtrlCore/GtkCapture.cpp, line 41 IsMainThread()"
AFAIK, this means that, that specific method -or other methods called within it- can only be called from the main thread.
In some cases you may want to create a customized event loop in the main thread.
E.g:
void Run()
{
OpenMain();
while(IsOpen()) {
ProcessEvents();
GuiSleep(10);
ProcessMyThreadsEvents(); // It's up to you how to precess your threads' events.
}
}
Best regards,
Oblivion
Github page: https://github.com/ismail-yilmaz
upp-components: https://github.com/ismail-yilmaz/upp-components
Bobcat the terminal emulator: https://github.com/ismail-yilmaz/Bobcat
[Updated on: Mon, 11 March 2019 13:06] Report message to a moderator
|
|
|
Re: How do I create a loop for a window to react to volatile changes to a global variable? [message #51336 is a reply to message #51335] |
Mon, 11 March 2019 13:29   |
slashupp
Messages: 231 Registered: July 2009
|
Experienced Member |
|
|
Hi Oblivion
What I do is more like this:
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
class ThreadTest;
void RunThread(ThreadTest *pTT);
class ThreadTest : public TopWindow
{
Button start;
ArrayCtrl array;
public:
ThreadTest()
{
SetRect(0, 0, 800, 600);
CenterScreen();
array.AddColumn("Number");
Add(array.HSizePos().VSizePos(0, 30));
Add(start.SetLabel("Start Thread").RightPos(2, 120).BottomPos(2, 26));
start << [=] { RunThread(this); };
}
void SetArray(int n)
{
GuiLock __;
array.Add(n);
if(n == 10) { // Resize window from within thread...
SetRect(0, 0, 640, 480);
}
}
};
void RunThread(ThreadTest *pTT)
{
Thread t;
ThreadTest *ptt=pTT;
t.Run([=]
{
for(int i = 1; i < 10; i++)
{
// GuiLock __;
ptt->SetArray(i);
}
});
t.Detach();
}
GUI_APP_MAIN
{
ThreadTest().Run();
}
Where the thread-func is global. This still works, and the only real difference
between my app and this is that I use std::thread ... maybe I shouldn't
I'll change my code to use Upp::Thread
(and if you don't hear from me again, it worked)
thx
|
|
|
|
Re: How do I create a loop for a window to react to volatile changes to a global variable? [message #54776 is a reply to message #51335] |
Thu, 10 September 2020 19:13   |
JeyCi
Messages: 67 Registered: July 2020
|
Member |
|
|
Oblivion wrote on Mon, 11 March 2019 12:44In some cases you may want to create a customized event loop in the main thread.
Yes it helps - thank you for the example.
But first example in your message also works U++ 13664 IN WIN32-MINGW_9.3-compiled - only if using
void SetArray(int n)
{
PostCallback([=](){
array.Add(n);
if(n == 10) { // Resize window from within thread...
SetRect(50, 50, 640, 480);
}
});
}
otherwise, I suppose, I'm getting into deadlock (with GuiLock & even with Call)app don't show changes to arrayCtrl & crashes... I think, that compiler matters!.. MSVC probably could compile ok MT app with GuiLock, or perhaps OS matters (probably Linux can have ok with GuiLock)...
But now with your example I see some possible changes to do to my own code - I could'n even assume, that answer is so easy - I thought (in my own code) that I made some mistakes in the code itself... of course will check again... but I agree with your proposal concerning MainThread... thank you for useful advice!
In any case, it seems, that compiler matters for Upp::Thread dealing with??...
therefore your suggestion seems suitable... thanks
Best regards.
[Updated on: Thu, 10 September 2020 19:26] Report message to a moderator
|
|
|
|
Goto Forum:
Current Time: Fri May 09 15:40:34 CEST 2025
Total time taken to generate the page: 0.01808 seconds
|