|
|
Home » U++ Library support » U++ MT-multithreading and servers » Thread calls GUI
Thread calls GUI [message #20056] |
Sat, 14 February 2009 19:26  |
Sami
Messages: 6 Registered: July 2008
|
Promising Member |
|
|
I realize a thread cannot call GUI in upp. It is not however clear how threading should be implemented then. I would ask help for proper solution to the example given below.
struct Interface {
virtual int Ask ( const char * ) = 0;
};
struct Work {
Interface *gui;
};
struct Library {
Library ( Work w ) {
int a = w.gui->Ask ( "Ok?" );
}
};
void Threading ( Work w ) {
Library ( w );
}
struct Task
:MyTask<TopWindow>
,Interface {
typedef Task CLASSNAME;
Task() {
CtrlLayout(*this, "Example" );
Work w;
w.gui = this;
Thread().Run ( callback1 ( Threading, w ) );
}
volatile Atomic q;
int Ask_Weird_Hacked ( const char *s, unsigned dummy ) {
return q = 1 + PromptYesNo ( String().Cat() << s );
}
int Ask ( const char *s ) {
//problem here, cannot call PromptYesNo()
q = 0;
PostCallback ( callback2 ( this, &Task::Ask_Weird_Hacked, s, 0 ) );
while ( !q ) Sleep ( 10 );
return q - 1;
}
};
So we begin with Task() and our problem is how to implement Ask() call properly. I first understood the Gate-method is what I'm looking for, but I didn't get it to work, can somebody explain what is it? The manual was in my opinion incomplete here.
[Updated on: Sun, 15 February 2009 00:14] Report message to a moderator
|
|
|
Re: Thread calls GUI [message #20058 is a reply to message #20056] |
Sun, 15 February 2009 08:24   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Unfortunately, Gate cannot work here. Gate is supposed to return the value, which is not possible until callback is performed..
I am afraid that the solution for your problem might be quite complex.
IMO, you will have to use something like Semaphore on thread part. Use PostCallback to signal to GUI thread you need that prompt, enter semaphore after PostCallback.
GUI thread then performs the prompt, signals the result via some shared variable, then releases semaphore of thread to get it going.
void DoAsk(Semaphore *sem, int *result)
{
*result = PromptYesNo("");
sem->Release();
}
struct MyThread {
int Ask() {
Sempahore sem;
int result;
PostCallback(callback2(DoAsk, &sem, &result));
sem.Wait();
return result;
}
}
(To my best knowledge, we do not need mutex for result, as sempahore does the synchronization for us as well).
(Not testes, but should work).
Mirek
|
|
|
|
Re: Thread calls GUI [message #20062 is a reply to message #20061] |
Sun, 15 February 2009 23:22   |
Mindtraveller
Messages: 917 Registered: August 2007 Location: Russia, Moscow rgn.
|
Experienced Contributor |

|
|
Some time ago I`ve started developing "alternative" multithreading system for U++. General idea is that you do not need any sync objects. Because threads do not see ANY shared variables. Instead threads have internal callback queues and exchange with callbacks. Realization is rather optimal (but could be better if I had more spare time ).
Recently I was badly needed this approach to be working for a number of threads and also for a "main" GUI thread. Finally these classes are ready and tested for some time, but still under heavy development.
Simplified code looks like this...
1. Declaring main GUI thread/window and one more thread:
class GUIThread : public CallbackQueue, public WithMainWindowLayout<TopWindow>
{
public:
GUIThread();
~GUIThread();
virtual void Init();
virtual void Shutdown();
void HandleIncomingMessages();
public /*sync*/:
void RefreshAll(const Drawing &bdr, const ControlGUI &cg);
void SetupBathsSettings(Vector<Vector<Value> > rows);
};
class IOThread : public CallbackThread, protected RS232
{
public:
IOThread();
~IOThread();
virtual void Init();
virtual void Shutdown();
public /*sync*/:
void GetAOpState(byte addr);
};
Main app function is simple:
GUIThread guiThread;
IOThread ioThread;
ControlThread controlThread;
GUI_APP_MAIN
{
try
{
CallbackQueue::InitAll();
CallbackQueue::StartAll();
guiThread.Sizeable().Run();
CallbackQueue::ShutdownAll();
}
catch (const Exc &ex)
{
PromptOK(ex);
}
}
Finally, if I want any of my threads (including main/GUI) to do something, I just request for this:
// i/o therads checks AOp devices and tells their availability to Control thread
void IOThread::GetAOpState(byte addr)
{
for (int i=0; i<attempts; ++i)
{
protoSend[3] = addr;
protoSend[4] = CMD_AOP_STATUS;
protoSend.Send(*this, timeout);
if (protoRecv.Receive(*this, timeout))
{
if ((int)protoRecv[3] != (int)addr)
continue;
controlThread.Request(&ControlThread::AOpStatus, addr, protoRecv[4]);
}
}
controlThread.Request(&ControlThread::AOpUnavailable, addr);
}
// Control thread analyzes system state and updates GUI accordingly
void ControlThread::SetupDisplayDrawing(bool enableSettings)
{
static ControlGUI cg;
// setting controls to be enabled/disabled
// ...
// drawing system elements and parameters
DrawingDraw d(DISPLAY_W,DISPLAY_H);
// ...
guiThread.Request(&GUIThread::RefreshAll, static_cast<Drawing>(d), cg);
}
...and no sync objects with their debug.
If this is handy for you, I`ll upload these "alternative" multithreading sources here.
[Updated on: Sun, 15 February 2009 23:50] Report message to a moderator
|
|
|
|
|
|
Re: Thread calls GUI [message #20099 is a reply to message #20086] |
Tue, 17 February 2009 15:57   |
|
How about to add semaphore method dword Semaphore::Wait(int timeout)?
in win32 is simple:
int Semaphore::Wait( int timeout )
{
dword result_value;
result_value = WaitForSingleObject(handle, timeout);
if(result_value == WAIT_FAILED) return(SEMAPHORE_WAIT_ERROR);
if(result_value == WAIT_TIMEOUT) return(SEMAPHORE_TIMEOUT);
}
but in POSIX is more hardly.
The good article found here.
I think it have sense on i have a postcallback and i know maximum execution time. Or I'm wrong?
|
|
|
|
Goto Forum:
Current Time: Tue May 13 13:59:56 CEST 2025
Total time taken to generate the page: 0.00678 seconds
|
|
|