DirectoryIterator question


#1

Seems like when I specify a directory and the recursive flag when constructing a new DirectoryIterator, it takes a looong time if the directory has many subdirectories.

This is rather bad, because if this is done in some Thread, I have no way to cancel this action (when the user presses “Cancel”, and the DirectoryIterator constructor is just constructing, the user will have to wait up to minutes until the Cancel action succeeds).

Is there no way to do this better? I mean, the DirectoryIterator should at least have a flag to stop it doing the scan - in my opinion, every action that can potentially take more than 0.25 seconds should be abortable. This is clearly not the case here.


#2

Yes, that’s a fair point. Not sure what the best pattern would be for making it abortable though.


#3

1st solution:

add an extra bool *abortFlag=0 to the constructor.
So this does not require changing old JUCE code.
If the pointer is non-zero, the first thing the constructor will do is initialize the bool flag to false. If some other Thread or whatever sets it to true, the constructor will leave ASAP.

2nd solution:

Just call Thread::getCurrentThread() and if it’s not zero, use threadShouldExit() to check if another Thread wants to abort the DirectoryIterator. I think this solution is the most logical, as anyway it would not be possible to stop the DirectoryIterator scanning if it was in the main (GUI) Thread (Ok, it would be possible, but I don’t see a scenario that does make much sense, like stopping it from another non-GUI Thread).


#4

I like your threadShouldExit idea, but what that’d mean is that the iterator might not actually return the correct result, and even if a thread has been told to die, you might still want the operations that it’s doing to complete correctly until the point where you decide to stop the thread. Hmm.


#5

What result? If the Thread’s told to exit, you anyway have to exit as fast as possible. The worst case would be that the DirectoryIterator would after construction return less files than there actually are. But anyway, if I program something like a Thread with a DirectoryIterator, and it can be cancelled by stopThread(), the absolutely first thing I’ll do is to check after the DirectoryIterator constructor if the Thread has been asked to exit with threadShouldExit(), so like this:

[code]void MyThread::run()
{
DirectoryIterator it;

// now use directory iterator
while (it.next() && !threadShouldExit())
{
// do some stuff with the iterator
File f=it.getFile();

}
}[/code]
I don’t see any problems with this, what might be the downsides?


#6

It’s just not a good idea to have a method that can, without warning, return the wrong result just because it has decided that you want it to stop.

It’d be perfectly valid to write a thread that doesn’t want the iterator to fail before it has finished doing its job, and in that case this would lead to some very puzzling bugs.


#7

Well, if that’s the only concern, then just add a bool to the constructor, like this:

DirectoryIterator(bool checkThreadShouldExit=false)

so the DirectoryIterator will only stop its construction when the Thread should exit and the programmer really wants it. I think that should be foolproof.


#8

TBH I can’t remember exactly why the class does the iteration in the constructor rather than during each callback, which would make this whole argument redundant. I’m sure there was a reason, but can’t remember it…