> > 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

Reply via email to