JUCE Singleton Implementation Confusion

Hey all,

I’m trying to instantiate a Singleton pattern GUI overhead. I stumbled upon the included Singleton ( https://www.juce.com/doc/juce__Singleton_8h ) and am trying to get it to work.

I’ve admittedly not done much with macros or pre-processor definitions, so most of this seems like witchcraft to me. I’ve been trying things and hoping that they’ll work, without a fundamental understanding of what’s going on.

Both explanations of what I need to do to complete this code, and what’s actually going on, would be very much appreciated! Resources/reading material are also appreciated.

Currently, I’m getting a Redefinition of _singletonInstance error in my macro definition in the ISWGUI header. Here’s my barebones code just trying to get the Singleton able to be instantiated (without any other methods for it yet)

ISWGUI.h
#ifndef ISWGUI_H_INCLUDED
#define ISWGUI_H_INCLUDED

#include "../JuceLibraryCode/JuceHeader.h"

class ISWGUI
{
public:
//JUCEy Singleton Wizardry
//==============================================================================
ISWGUI(){}
~ISWGUI()
{
clearSingletonInstance();
}
juce_DeclareSingleton(ISWGUI, true);
//true bool ensures deletion in PluginProcessor releaseResources holds
//==============================================================================
};

//Macro for Singleton
juce_ImplementSingleton(ISWGUI)

endif // ISWGUI_H_INCLUDED

ISWGUI.cpp
#include "ISWGUI.h" juce_ImplementSingleton(ISWGUI)

that last line is giving me my error.

As far as I can see you have the implementation twice, one in the header and one in the cpp.
I think you can remove the one from the header…

headdesk yep. Thanks for pointing that out.

((I’d still love for others to chime in on what’s going on with all of the macros/definitions, though!))

It’s actually pretty straightforward, just the macro that’s probably confusing you if you’re not experienced with them. It’s worth spending the time to understand how they work since they crop up in JUCE somewhat commonly. Essentially they’re just text substitutions. Before your code is compiled, it’s handed to a preprocessor. This is where things like #include “stdio.h” are replaced with the actual text from stdio.h before being given to the compiler. That same preprocessor also takes each macro and handles it similarly to the includes by replacing that macro with the code it represents, same with defines (Kinda more complicated, but this is intuitively what’s happening). Not sure what your dev environment is, but Resharper’s newish C++ extension for Visual Studio lets you substitute code for macros (like the preprocessor does behind the scenes) which makes it easy to figure out what they’re doing without having to dig around in JUCE’s code.

Using it on juce_DeclareSingleton and juce_ImplementSingleton both shows that what’s happening inside the macros is just a traditional singleton implementation–you get a single static instance of your class, static methods to retrieve and delete it, and a mutex lock used internally that you can ignore for your purposes. There’s nothing special happening, the macros are just used to hide the boilerplate singleton code. In fact, not that I did this myself or anything… but if a person were to be dumb enough not to realize JUCE already provided these nice macros and that person wasted time writing their own singleton implementation for a few classes, that code looks virtually identical to the code hidden by the macros. :smile:

Thank you for the info!

Alright, so- I didn’t stumble upon JUCE’s singleton by browsing the API- I stumbled upon it because I started typing the word ‘singleton’ to label a section of code, forgetting to include the comment markers as I did so, and XCode popped up with one of the JUCE methods… >.>

I’ve only done singletons in Java coding before, and initially attempting to make my own in C++ was… an experience.

HA I wish I’d stumbled into it that way before I wasted time writing my own. I turn VS’s completion autopopups off because they tend to obscure half the code I need to see more than they help, but I pay for it sometimes…

I recently had more or less the same requirement for a singleton and used juce::SharedResourcePointer<T>

worked well for me.

The difference is that this one deletes the singleton as soon as all references to it have been released. That was exactly what I wanted, but if your singleton should keep its state even when nobody has a reference to it then it might not be what you need

2 Likes

Oh hey another thing I’m glad to know exists now, thanks for pointing that out.