OpenGLComponent and Threading problem


#1

Hi again,

After sometime playing around , I finally wrote my code but it doesn’t work. I wanted to do computation and rendering in an OpenGLcomponent and meanwhile have an AlertWindow with a progressbar to show the total progress. I wrote the code below. which I learned mostly from ThreadWithProgressWindow.

class ApproxCanvas : public OpenGLComponent,
               			public Thread,
				private Timer
{
private :
	//...
       double progress;
       AlertWindow alertWindow;

	ApproxCanvas(const ApproxCanvas &);
        const int timeOutMsWhenCancelling;
	void timerCallback();
public :
	juce_UseDebuggingNewOperator
	ApproxCanvas() : Thread ("Approximation Progress Window"),
			           progress (0.0),
			           alertWindow (JUCE_T("Window"), String::empty, AlertWindow::NoIcon),
			           timeOutMsWhenCancelling (10000)
	{
		alertWindow.addProgressBarComponent (progress);
		alertWindow.addButton (TRANS("Cancel"), 1);
	}
	~ApproxCanvas()
	{
		stopThread (timeOutMsWhenCancelling);
	}
	bool runThread (const int threadPriority = 5);
	void setStatusMessage (const String& newStatusMessage);
	void setProgress (const double newProgress);
	//---------------------------------
	void newOpenGLContextCreated();
	void renderOpenGL();
	void run();
};
void ApproxCanvas::run()
{
	if (!makeCurrentContextActive())
	{
		DBG("run - failed"); // will send a message to debug output 
                                             // the program pass from here and never 
                                             // reach the main loop of computation 
                                             // when using in threading mode
		return;
	}

	while(1) 
        {
              //  ... computation or rendering
		setProgress(...);
              if (stopCondition)
                     break;
              // ... computation or rendering
        }   
}

bool ApproxCanvas::runThread (const int priority)
{
    startThread (priority);
    startTimer (100);

    alertWindow.setMessage (message);

    const bool wasCancelled = alertWindow.runModalLoop() != 0;

    stopThread (timeOutMsWhenCancelling);

    alertWindow.setVisible (false);

    return ! wasCancelled;
}


void ApproxCanvas::setProgress (const double newProgress)
{
    progress = newProgress;
}

void ApproxCanvas::setStatusMessage (const String& newStatusMessage)
{
    message = newStatusMessage;
}

void ApproxCanvas::timerCallback()
{

    if (! isThreadRunning())
    {
        // thread has finished normally..
        alertWindow.setVisible (false);
    }
    else
    {
        alertWindow.setMessage (message);
    }
}

The problem is that when I start the computation by ApproxCanvas->runThread(); , for a fraction of a second the AlertWindow with the ProgressBar appears and send the debug text to the output “run-failed”. means that the context is not active and it returns.

but

when I start witout Treading by ApproxCanvas->run(); it works fine but without any progressWindow.

I tried to lock the context but it didn’t work or I just don’t know how to lock the context.

what should I do ? I am working about 15 hours on this problem. trying anything that came to my mind. but I couldn’t solve it. should I forget about the ProgressBar ?


#2

You can’t call stopThread on the thread that you’re trying to stop! (Actually, I might see if I can add an assertion to catch people doing that)

Did you look at ThreadWithProgressWindow?


#3

I just copied the followings from ThreadWithProgressWindow

::runThread (const int priority)
::setProgress (const double newProgress)
::timerCallback()

so you think that if I comment out the line stopThread(), the program might work ?


#4

Well no, you can’t run a modal loop on a thread, either… Sorry, your code just looks very confused, I can’t make any sense out of it… Why not just use a ThreadWithProgressWindow like it’s supposed to be used?


#5

Thank you. I think I had some misunderstanding about the concept of Threads. well I don’t know how and where to define the ThreadWithProgressWindow.

I have my OpenGLComponent registered to a Window that works and do some computation and rendering. if I want to have this progress window, should I define a class : public ThreadWithProgressWindow and add it to my OpenGLComponent ? and if I do that and put some of my computation in it’s run() actual thread code, how should I address the variables which are belong to it’s parent ?

What happends to OpenGLContext inside this class and all variables that currently I have defined in my OpenGLComponent ?


#6

What you’re asking is “how do I program threads correctly?”… which is a bit beyond the scope of this forum! There’s an example of how to use a ThreadWithProgressWindow in the juce demo somewhere, I think.


#7