5A281DE0 mov eax,dword ptr [eax+64h]
jassert(directoryList != nullptr);
while (directoryList->isStillLoading()) {}
5A281DE3 test eax,eax
5A281DE5 jne PresetBrowser::refresh+53h (5A281DE3h)
If I'm reading this right, it is the digital equivalent of guarding a bank by taking a picture, going to the pub and staring at the picture. Am I reading it right?
The function isStillLoading() does this: {return fileFindHandle != nullptr;}
fileFindHandle is updated by another thread.
The compiler misses this entirely and copies fileFIndHandle directly into eax and then keeps checking eax to see if it's turned into a nullptr yet.
It doesn't.
I can disable optimisation for this function, but this is so broken ... is there something I'm doing wrong with the complier?
It's only pausing a fraction of a second in the GUI after it's saved a new preset - hasn't caused any problems to date. But you are right I could deal with this in a different way by refreshing the menu and let it read the disk in the background. I'll have a think about that, it'll work find where I'm using a tree view I think, but I'm not sure when i'm refreshing the popupmenu with the presets that there's an easy way of updating a popupmenu which is already popped?
And if this is the message thread, you should never run a loop of any kind at all - always use a timer or other callback to wait for things.
The compiler is treating it as a single operation, and deciding that it's ok to cache the result of the method call - probably if you stuck a sleep(1) in the middle, it'd be unable to make that optimisation. But really, you shouldn't be writing code like that in the first place.
I still find the problem rather interesting though. It feels like there's a gap that something like 'volatile' ought to fill to ensure that you get the desired behaviour out of a multi-threaded programme. Surely there are situations when blocking until another thread completes is a reasonable course of action?
Surely there are situations when blocking until another thread completes is a reasonable course of action?
Nope. Maybe if you're implementing an OS kernel or something, but not at the app level.
The 'volatile' keyword is generally avoided in C++ these days - the way to do it in C++11 is via the new memory model and atomic<>. But yes, you're right - to be strictly correct, I should have made the pointer atomic to force the compiler to treat it as being volatile.
Good to know how to handle it in case it does come up. Still, the while loop is now history, consigned to the dustbin (though archived in git forever...)