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: 163
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: 545
Registered: August 2007
Location: Turkey
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: 163
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 message
Didier is currently offline  Didier
Messages: 476
Registered: November 2008
Location: France
Senior Member
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
Previous Topic: WebSockets client in javascript connected to an U++ server sending binary messages
Next Topic: SSH package for U++
Goto Forum:
  


Current Time: Mon Mar 25 20:54:33 CET 2019

Total time taken to generate the page: 0.01490 seconds