Problem with TreadWithProgressWindow again


#1

hi,

sorry, It is me again. but after a hundred trials and errors, I finally am able to document the problem as understandable as possible. hope someone would help me with a practical solution.

this is the code of TreadWithProgressWindow exctaly defined in juce demo.

class DemoBackgroundThread  : public ThreadWithProgressWindow
{
public:
    DemoBackgroundThread()
        : ThreadWithProgressWindow (T("busy doing some important things..."),
                                    true,
                                    true)
    {
        setStatusMessage (T("Getting ready..."));
    }

    ~DemoBackgroundThread()
    {
    }

    void run()
    {
        const int thingsToDo = 10;

        for (int i = 0; i < thingsToDo; ++i)
        {
            // must check this as often as possible, because this is
            // how we know if the user's pressed 'cancel'
            if (threadShouldExit())
                break;

            // this will update the progress bar on the dialog box
            setProgress (i / (double) thingsToDo);

            wait (500);

            setStatusMessage (String (thingsToDo - i) + T(" things left to do..."));
        }
    }
};

now if I run this thread like this :

class aClass 
{
   public :
   aClass () {}
   ~aClass() {}
   void this()
   {
         DemoBackgroundThread m;
         m.runThread();
   }
   
};

everything works file. I am able to run this() for any number of times and no problem. but I really need to define the Thread like below :

class aClass 
{
   DemoBackgroundThread* m;
   public :
   aClass () 
   {
        m = new DemoBackgroundThread;
    }
   ~aClass() 
   {
        delete m;
   }
   void this()
   {
         m.runThread();
   }
};

and the aClass is not going to be destructed till the end of the application and has many other members and variables. but even in the simplest form like above it has a problem.

when I call this() , for the first time the ThreadWithProgressBar appears and do it’s work fine. if I press cancel . and again call this() no problem occurs. but the first time that the Thread exits normally without clicking the cancel button. the next time by calling this() , visual studio triggers a breakpoint but every variables and everything seems normal. by clicking continue the thread appears and do it’s job normally. but why does it trigger a breakpoint trigger all about ? It is just making me crazy.

please I really need to use the threadWithProgressWindow in this way with new and delete operators. it would be great if someone really test this code. I think it might be bug.

:: Nikola Williams


#2

why do you so desperately need them to exist on the heap? if you’re making the object exist for the entire lifespan of your class, then you could just as easily make it a member object. also, why do you need it to exist for the entire lifespan of the object? i can think of no reason why you’d need to have such an object lying around for longer than it’s needed, unless you were using it to buffer stuff in the mean time; even then, you could just provide that information when you create it.

but also you haven’t given any information on where it breaks. is it in some juce code perhaps? it could be an assert with some useful comments explaining the cause of the problem.


#3

well , aClass is my mainContentComponent of the juce application. and the Thread I mentioned is an openGLComponent too with some Cg Fragment programs , frame buffers , textures and … so I can’t delete it

the breakpoint triggers exactly at the end of the this() on the } or any other line just after the runThread(). what kind of information can I evaluate from my program to paste here ?


#4
class aClass
{
   DemoBackgroundThread m;
   public :
   aClass ()
   {}
   ~aClass()
   {}
   void this()
   {
         m.runThread();
   }
};

I tested the above code and the problem exists again.

TIN.exe has triggered a breakpoint


#5

The problem only occurs in debug mode, when I compile the program in release mode , no problem occurs. how can I make this studpi compiler understand not to trigger a breakpoint over this line ?


#6

You’re using juce as a DLL… So if you want to debug it, you’ll need to make sure the debugger can find all the necessary files for that DLL. Why not just statically link it and make your life easier?


#7

does that really help to find out when the jassert commit the trigger ? beacuse the static library is so huge about 135meg. but the dll file is only 2 or 3 mega bytes.


#8

yes, it makes everything in life a whole lot easier! unless you have a very serious reason to be using juce as a dll (and i can’t even think of one) you’re really going to find everything easier if you link statically. i imagine that if you were that low on HD space that you couldn’t afford to give some to Juce, you’d probably run out before you had many projects built anyway!


#9

Dude !!! WoW . Thanks . you saved my life. at least now I know where the problem is and where the breakpoint occures but I am not able to solve it. do you have any idea ?

JUCE_COMPONENT.CPP -->

void Component::enterModalState (const bool takeKeyboardFocus)
{
    // if component methods are being called from threads other than the message
    // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
    checkMessageManagerIsLocked

    // Check for an attempt to make a component modal when it already is!
    // This can cause nasty problems..
->  jassert (! flags.currentlyModalFlag);

    if (! isCurrentlyModal())
    {
        modalComponentStack.add (this);
        modalComponentReturnValueKeys.add (this);
        modalReturnValues.add (0);

        flags.currentlyModalFlag = true;
        setVisible (true);

        if (takeKeyboardFocus)
            grabKeyboardFocus();
    }
}

when for the second time I try to run the Thread in my program, The breakpoint occurs in line 6 . but I am sure I didn’t enterTheModalState(). and even when I try to exitTheModalState() just before the runThread() , I get the same breakpoint.

Is it a bug or something ?


#10

Well no, it’s not going to be a bug - like the comment says, you’re trying to make something modal twice.

Stick some breakpoints in enterModalState and find out where you call it from. That’s that whole point in having a debugger!


#11

Oh , It is a bug and the bug is in AlertWindow.

when the AlertWindow.runModalLoop() is called. when the loop breaks normally. no one is able to call this runModalLoop() again until the AlertWindow get deleted. the cause might be the modal flags or from exit modal state . don’t know which.

so I had to code it myself in my program to just create the alertwindow before calling runModalLoop() and delete it after the loop breaks


#12

I’m not sure what problem you’re having, but I can call runModalLoop() on a single AlertWindow any number of times without problems.


#13

AlertWindow w ("foo", "bar", AlertWindow::NoIcon); w.addButton ("ok", 0); w.runModalLoop(); w.runModalLoop();

The code above works fine. If you really think there’s a bug (and I doubt this very much), then show me an example bit of code which which fails, and I’ll look into it.


#14

Aha, it IS a bug, and it’s fixed with this minor addition…

juce_ThreadWithProgressWindow.cpp

89  void ThreadWithProgressWindow::timerCallback()
90  {
91     if (! isThreadRunning())
92     {
93        // thread has finished normally..
94        alertWindow.exitModalState (0);
95        alertWindow.setVisible (false);
96     }
97     else
98     {
99         alertWindow.setMessage (message);
100    }
101 }

Personally though, I don’t understand why you’re making the OpenGLComponent a ThreadWithProgressWindow. I can’t percieve a situation where it fits in as a logically defined classification; inheriting a class says ‘this type IS one of these’, but a ThreadWithProgressWindow is just not the sort of thing that an OpenGLComponent would ‘be’. I can understand you wanting a thread (for rendering, or updating what is to be rendered) - but a progress window is modal and would surely obscure what you might be rendering.

It makes a lot more sense, in both logical terms AND sound program design, to just create such an object when it’s needed, so you don’t end up with poorly defined and classified object types. One of the biggest challenges with C++ coding is striking the right balance when it comes to class functionality and purpose distribution. There are always a scrillion ways of making your way to the goal, but usually fairly few that are elegant enough to make it (a) easy to use and understand, (b) reusable and © expandable.

When you do achieve this, you usually find that it’s because you’ve taken the time to ensure your classes just ‘make sense’. That is, if you were to visualise their functionality and interaction with each other, you could almost associate them with real physical objects. Members are things it has, functions are things it does, and base classes are things that define what it IS. I can’t think of any situation where it would make sense for an OpenGLComponent to ‘be’ a ThreadWithProgressWindow; it could HAVE one (and starting it is something that it ‘does’), or it could be some target of an external one, but I don’t think it would ever logically ‘be’ one.

All that said, I’m not going to try to tell you that what you’re doing is wrong; in programming there are always odd cases lurking around waiting to demand an unorthodox implementation, and I don’t have the knowledge or authority to determine that yours isn’t one of them! The situation just prompted me to provide some topical off-the-cuff C++ coding advise (just in case you hadn’t thought it through fully).

Feel totally free to ignore as much of this post as you like! Although I imagine the fix at the top will be of interest :wink:


#15

Oh no! A real bug! I’m sorry I doubted you!

Thanks for figuring it out haydxn. Using setVisible (false) will automatically make a component exit the modal state too, but this only gets done when the next message gets delivered. So in this case that won’t have happened by the time you call enterModalState again. That’s my excuse, anyway…


#16

Hi haydxn,

I know it seems strange to make an OpenGLComponent a ThreadWithProgressWindow too. but I didn’t find any way to do the job. I am doing some computaion and rendering using CG shading language. meanwhile when The computation is doing it’s job, I needed a progress Window to show the progress. since I had to write my computaion algorithm inside the run() from ThreadWithProgressWindow, I could n’t just build it and pass all the variables and pointers like, Framebuffer, all Textures, shading programs , … . there are just too many. so I had to do it in this way. and thanks for the fix. thanks to jules too.

but now I have another problem which seems too be another bug. I am working on that now. if I couldn’t find a way , I might post a new topic. The problem is that when I run the computation in Thread mode, sometimes, the heap gets corrupted. but just sometimes and could be anytime.

thanks a lot

Nikola


#17

Hi,
I’m using a ThreadWithProgressWindow derived class in my project for searching files in the drives. I create a new ThreadWithProgressWindow for each existing first level directory and I’m updating the status message for each sub-directory of the current first level directory the program is parsing in the run method

I’d sometimes a message in the XCode log - but never at the same moment:
"malloc error for object 0x…: incorrect checksum for freed object - object was probably modified after being freed."
And sometimes i’ve a crash.

I’ve tried to comment message = newStatusMessage in the setStatusMessage method of ThreadWithProgressWindow. I’ve have no more crashes or malloc error log messages.

Then i’ve added a CriticalSection object member in the ThreadWithProgressWindow declaration and added some ScopedLock myLock(myCritical) declaration at the beginning of setStatusMessage, timerCallback, destructor methods and have commented the
and alertWindow.setMessage (message) in the runThread method.

Again no more crashes or messages.
It seems that there is a thread issue on the message member of ThreadWithMessageWindow as it can be modified by setStatusMessage while it’s also used int the AlertWindow setMessage method.
But i’m surely missing something, or doing something wrong in my call…
I’ve checked your example, but didn’t notice any critical differences, except the wait(500) you’ve added in the run method.


#18

Hmm - that’s interesting. I didn’t expect there to be any need to lock that assignment, because the string copy operation should work atomically… There must be some other operation being done to the string that’s messing it up. To be on the safe side, I’ve checked in a version now with a lock around the assignment. Thanks!


#19

Thanks Jules!!!
As the message is passed as reference, in the setStatusMessage, could it be the reason?
There’s an explicit copy in the setMessage of AlertWindow - called by the timerCallback - but a substring is made just before.


#20

No, I can’t see why it’s going wrong like that. Oh well, a lock in there doesn’t do any harm.