Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
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 Go to next message
slashupp is currently offline  slashupp
Messages: 207
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 Go to previous messageGo to next message
Oblivion is currently offline  Oblivion
Messages: 735
Registered: August 2007
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


[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 Go to previous messageGo to next message
slashupp is currently offline  slashupp
Messages: 207
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 #51359 is a reply to message #51336] Thu, 14 March 2019 22:11 Go to previous messageGo to next message
Didier is currently offline  Didier
Messages: 569
Registered: November 2008
Location: France
Contributor
Hello Slashupp,

Maybe you should try using 'PostCallback()'

1 - Use PostCallback( UpdateCB ) in the thread modifying the variables
2 - In the GUI thread, UpdateCB() will get called and will do the update work

Note : a mutex is still needed to protect the variable UNLESS these variables can be set/read atomically

Didier
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 Go to previous messageGo to next message
JeyCi is currently offline  JeyCi
Messages: 9
Registered: July 2020
Promising Member
Oblivion wrote on Mon, 11 March 2019 12:44
In 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 Embarassed - 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??... Shocked
therefore your suggestion seems suitable... thanks


Best regards.

[Updated on: Thu, 10 September 2020 19:26]

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 #54778 is a reply to message #51336] Thu, 10 September 2020 19:17 Go to previous message
JeyCi is currently offline  JeyCi
Messages: 9
Registered: July 2020
Promising Member
P.S.
slashupp wrote on Mon, 11 March 2019 13:29

Where the thread-func is global.

global functions as I remember can have problems being compiled with MSVC... if I'm wrong?


Best regards.
Previous Topic: AsyncWork, IsFinished() may not be working properly
Goto Forum:
  


Current Time: Sun Sep 27 21:09:07 CEST 2020

Total time taken to generate the page: 0.01335 seconds