> > My program has two child threads, thread1 and thread2 spawned
> > from the main thread. when a button from the main thread is clicked,
> > it checks user's selections on three check boxes. The checks can be
> > in any combination, but they always be executed in sequence.
> >
> > Thread1 is in charge of running three heavy calculations
> > and thread2 is in charge of displaying results immediately
> > after each calculation to the GUI. I have both threads
> > created in main in the suspended states. When the button
> > is clicked, thread1 starts doing his jobs. Once thread1
> > finishes his first job, it resumes thread2 to update the
> > results to the screen. In the mean while, thread2 continues
> > to do his second job.
>
> If you're going to do anything with the screen,
> I'd suggest doing it in the main FLTK thread.
>
> You can have the main thread start an FLTK timer
> that triggers every 1/30th of a second (or whatever)
> to watch a buffer that thread #1 appends data to
> whenever its ready.
>
> Use a lock to make sure the main loop doesn't
> try to read data while thread #1 is writing it.
>
> > The question I have is how do I put thread2 to pause
> > until thread1 finishes his second job, then thread2
> > can update the results to screen, then continue one
> > in this fashion. I do not want to use busy wait loop,
> > because it will eat up lots of cpu time. What is the
> > best approach here in this case?
>
> If you really want two extra threads in addition
> to the main thread, seems like a mutex lock would
> be good for this.
>
> Basically thread #2 blocks on a lock that thread #1
> creates. When thread #1 has data ready, it unlocks,
> waking thread #2 so it can do its display work.
>
> You may need two locks to ensure one thread never
> gets ahead of the other.
>
> This should allow both thread #1 and thread #2 to
> do their work at the same time, while preventing
> one from getting ahead of the other.
>
> With the pthreads library I think this would be
> done with pthread_mutex_lock()/unlock.
>
> Watch for races and deadlocks when you do this
> sort of thing.
Thanks for comments from all of you. I created a sample code using Event
objects to alternatively locking/unlocking the threads. I have the problem of
unresponsive GUI. I paste my sample code here to get some helps. If you think
my code is not effective, please advice me to get a better approach. Thanks in
advance.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Hor_Slider.H>
#include <FL/math.h>
#include <FL/Fl_Int_Input.h>
#include <FL/Fl_Output.h>
#include <FL/Fl_Button.h>
#include <FL/Fl_Check_Button.h>
#include <FL/fl_ask.H>
#include <stdio.h>
#include <cstdlib>
#include <process.h>
#include <windows.h>
#include "aclapi.h"
Fl_Output* output_2;
Fl_Output* output_3;
Fl_Window *window_2;
Fl_Window *window_3;
Fl_Int_Input *idIniOrder;
Fl_Output *cb_infoN;
Fl_Button *start;
Fl_Check_Button *check1;
Fl_Check_Button *check2;
int processID = 0;
int processAC = 0;
const int numThreads = 2;
HANDLE threadArray[numThreads];
HANDLE driveSystemEvent;
HANDLE systemIDEvent;
int v[1000000];
static void start_cb(Fl_Button *b, void *p);
static void check1_cb(Fl_Button *b, void *p)
{
processID = check1->value();
}
static void check2_cb(Fl_Button *b, void *p)
{
processAC = check2->value();
}
void make_first_window()
{
char tmp_s[10] = "19";
start = new Fl_Button(1,1,65,20, "&Start");
start->callback( (Fl_Callback*) start_cb );
start->labelsize(14);
start->tooltip("Save parameters and run close loop");
check1 = new Fl_Check_Button(1, 40, 65, 20," System ID");
check1->when(FL_WHEN_CHANGED);
check1->labelsize(13);
check1->callback((Fl_Callback*) check1_cb);
check2 = new Fl_Check_Button(1, 70, 65, 20," PFF AC");
check2->when(FL_WHEN_CHANGED);
check2->labelsize(13);
check2->callback((Fl_Callback*) check2_cb);
}
void window_1_cb(Fl_Widget *o, void *p) {
exit(0);
}
void window_2_cb(Fl_Widget *o, void *p) {
exit(0);
}
void PlotGraphs()
{
char msg[256];
DWORD rc, waitResult;
int j;
window_3->show();
for (j=0; j<1000000; j++)
{
waitResult = WaitForSingleObject(systemIDEvent, INFINITE);
switch (waitResult)
{
case WAIT_OBJECT_0:
// Event object was signaled
sprintf(msg, "%d", v[j]);
Fl::lock();
// Obtain a lock before we access the browser widget...
output_3->value(msg);
output_3->redraw();
Fl::unlock();
// Release the lock...
Fl::awake();
rc = ResetEvent(systemIDEvent);
if (!rc)
printf("ResetEvent systemIDEvent failed
(%d)\n", GetLastError());
rc = SetEvent(driveSystemEvent);
if (!rc)
printf("ResetEvent driveSystemEvent
failed (%d)\n", GetLastError());
break;
default:
printf("Wait error (%d)\n", GetLastError());
break;
}
}
rc = ResetEvent(driveSystemEvent);
}
unsigned WINAPI RunProcesses(LPVOID lpParam)
{
char msg[256];
int i;
DWORD rc, waitResult;
for (i=0; i<1000000; i++)
{
waitResult = WaitForSingleObject(driveSystemEvent, INFINITE);
switch (waitResult)
{
case WAIT_OBJECT_0:
// Event object was signaled
v[i] = i;
rc = ResetEvent(driveSystemEvent);
if (!rc)
printf("ResetEvent driveSystemEvent
failed (%d)\n", GetLastError());
rc = SetEvent(systemIDEvent);
if (!rc)
printf("ResetEvent systemIDEvent failed
(%d)\n", GetLastError());
break;
default:
// An error occurred
printf("Wait error (%d)\n", GetLastError());
return (unsigned)0;
}
}
return (unsigned)1;
}
static void start_cb(Fl_Button *b, void *p)
{
DWORD rc;
unsigned threadID;
char msg[256];
sprintf(msg, "%s", "");
Fl::lock(); // Obtain a lock before we
access the browser widget...
output_3->value(msg);
output_3->redraw();
Fl::unlock(); // Release the lock...
Fl::awake();
driveSystemEvent = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE,
"DriveSystem");
systemIDEvent = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE,
"SystemID");
if (processID)
{
threadArray[0] = (HANDLE)_beginthreadex(NULL, 0, &RunProcesses,
NULL, 0, &threadID);
if ( threadArray[0] == 0 )
printf("Failed to create thread 1\n");
rc = SetEvent(driveSystemEvent);
if (!rc)
printf("SetEvent failed (%d)\n", GetLastError());
PlotGraphs();
}
}
int main(int argc, char **argv) {
Fl::lock();
unsigned threadID;
DWORD rc;
driveSystemEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("DriveSystem") // object name
);
if (driveSystemEvent == NULL)
printf("CreateEvent failed (%d)\n", GetLastError());
rc = SetSecurityInfo(driveSystemEvent, SE_KERNEL_OBJECT, SYNCHRONIZE |
EVENT_MODIFY_STATE, NULL, NULL, NULL, NULL);
if (!rc)
printf("Failed to SetSecurityInfo\n");
systemIDEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("SystemID") // object name
);
if (systemIDEvent == NULL)
printf("CreateEvent failed (%d)\n", GetLastError());
rc = SetSecurityInfo(systemIDEvent, SE_KERNEL_OBJECT, SYNCHRONIZE |
EVENT_MODIFY_STATE, NULL, NULL, NULL, NULL);
if (!rc)
printf("Failed to SetSecurityInfo\n");
Fl_Window *window = new Fl_Window(100, 100, 200, 100, "1 Window");
window->begin();
make_first_window();
window->callback(window_1_cb);
window->end();
window->show(argc,argv);
window_3 = new Fl_Window(100, 400, 200, 100, "3 Window");
window_3->begin();
output_3 = new Fl_Output(10,10, 100, 25);
output_3->color(FL_BACKGROUND_COLOR);
output_3->labelsize(14); // 14 is default
output_3->type(14);
output_3->textsize(14);
window_3->end();
window_3->hide();
window_3->resizable(window_2);
WaitForMultipleObjects(2, threadArray, TRUE, INFINITE );
return Fl::run();
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk