Here’s what I did, I made File::nonexistent a function instead of a global. Then I used my SharedSingleton to initialize it. These are reference counted singletons that are dynamically allocated and all “hang” off a single static object (managed by ONE global called PerformedAtExit):
// We need to make a shared singleton or else there are
// issues with the leak detector and order of destruction.
class NonexistentHolder : public SharedSingleton <NonexistentHolder>
: SharedSingleton <NonexistentHolder> (SingletonLifetime::persistAfterCreation)
static NonexistentHolder* createInstance ()
return new NonexistentHolder;
File const file;
File const& File::nonexistent ()
return NonexistentHolder::getInstance ()->file;
This utilizes all the things that I have talked about over the last 2 years regarding objects with static storage duration, zero-initialization of static objects without constructors, and the concepts of reference counted singletons.
Ultimately the solution comes down to:
- Never create objects with static storage duration anywhere in JUCE, Beast, or client code
- Always use SharedSingleton for global variables
This especially applies to function level objects with static storage duration, such as in getCurrentThreadHolder():
static CurrentThreadHolder::Ptr getCurrentThreadHolder()
static CurrentThreadHolder::Ptr currentThreadHolder; // BAD!!!
VFLib has the suite of tools of dealing with this issue, if you remember I posted a utility class “StaticObject”. It tidys up constructs like this:
static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros).
static StaticObject <SpinLock> currentThreadHolderLock;
Here’s the old post:
Generic StaticObject, any static var can be thread safe!
This is exactly why I changed the prefix from juce_, I’ve been methodically rewriting the entire forked juce_core module to use these techniques so that the leak checking and what not actually works right.
I highly doubt you want to adopt ALL of these changes just to fix order of construction and destruction issues right (and make those solutions available to JUCE users)… or do you?