ImageFileFormat initialization problem?


#1

Hi,

My app crashes directly after starting up in juce_ImageFileFormat.h, line 54. When I examine the formats variable I see that the entry for jpg is 0.

I call ImageFileFormat::loadFrom from a few different threads very soon during startup. Could this be the problem?

Patrick


#2

Sounds like it to me:

ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input)
{
    static PNGImageFormat png;
    static JPEGImageFormat jpg;
    static GIFImageFormat gif;

    ImageFileFormat* formats[4];
    int numFormats = 0;

    formats [numFormats++] = &png;

Not thread safe in every build environment! Try calling findImageFormatForStream () once from your message thread to initialize it safely as a workaround.

But Jules should really fix this once and for all…I posted extensively on this topic elsewhere.


#3

This fixes it if executed before any threads are started:

	// Force juce to initialize image formats
	std::vector<unsigned char> dummy(1);
	MemoryInputStream stream(&dummy[0], dummy.size(), false);
	ImageFileFormat::findImageFormatForStream(stream);

Patrick


#4

// Force juce to initialize image formats std::vector<unsigned char> dummy(1); MemoryInputStream stream(&dummy[0], dummy.size(), false); ImageFileFormat::findImageFormatForStream(stream);

Wow that looks like my friend’s ugly sister! Jules save us from this trainwreck!


#5

None of the graphics code was ever designed to be thread-safe! Making everything safe would have been enormously complicated, so although a lot of it will work (and certainly the image-loading should be ok), it comes with no guarantee!

In fact, looking at that bit of code again, it’d have been better to write it as a file static, e.g.

[code]struct DefaultImageFormats
{
PNGImageFormat png;
JPEGImageFormat jpg;
GIFImageFormat gif;
};

static DefaultImageFormats defaultImageFormats;

ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input)
{
ImageFileFormat* formats[] = { &defaultImageFormats.png,
&defaultImageFormats.jpg,
&defaultImageFormats.gif };
[/code]

…since there’s no real space or time saving in lazily creating the format objects (which are basically just empty objects), and writing it this way will make the compiler produce far less boilerplate code, as well as avoiding your threading issues.