ValueTree is not static friendly

For a demo purpose I wanted to make a static ValueTree.
Tested on macOS.
I didn’t get to the bottom of it but you can simply reproduce this doing the following -

  1. create a JUCE app.
  2. in some main cpp or h add your static object such as
static ValueTree staticVT { "ValueTree", {{"static", "constructor" }}};

On the compiled binary you’ll hit the following -
image

Another thing I’ve tried that failed was -
creating an empty juce::ValueTree and from my constructor:

if (!myValueTree.isValid())
{
    myValueTree = ValueTree { "ValueTree", {{"static", "constructor" }}};
}

This one could lead to leakage.

I know this isn’t a common use case for ValueTrees but thought it’s worth posting/reporting.

I think any non-trivial statics are basically dangerous.
You can use the Meyers singleton pattern though? (I.e. wrap it in a function so it only gets initialised on the function call).

1 Like

Thanks, our need was just on some sample code. and the new constructor looked cleaner.

Eventually a static ValueTree foo (“foo”);
and setting it up on our instance constructor was working. but code wasn’t clean as both snippets I’ve posted.
(we didn’t want to have too much code for this example).

I wondered but didn’t find it there’s a way to set a class to don’t allow static instances of it. but that’s another story.

Have you found a work around to it?

https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use

1 Like

I’ve found a workaround for this. The problem is that you can’t statically initialize a var (presumably because of the static initialization order fiasco). However, there is nothing stopping you from initializing an invalid static ValueTree. Then you can initialize it from within the initialize() method inside your JUCEApplication in Main.cpp. You also have to de-initialize it inside the shutdown() method, by doing myStaticValueTree = ValueTree(). If you don’t do this, you’ll hit a leak detector.

The static ValueTree can’t be const, but this seems like a small trade-off. I’m finding this to be a useful way of giving my class some simple system wide settings, without having to pass it in through the constructor.

Another possibility is to use a SharedResourcePointer.

Since the JUCEApplication itself is a singleton, it is a perfect place to store application wide data with a deterministic lifetime. Just add a static function to your application. For that purpose it is advisable to separate it in a MyApplication.cpp/MyApplication.h to simplify includes:

class MyApplication : public JUCEApplication
{
public:
    void initialise (/* yada yada */)
    {
        // restore settings
    }
    ValueTree& getSettings()
    {
        return settings;
    }

private:
    ValueTree settings { "Settings" };
};

namespace Settings
{
    static ValueTree& getSettings()
    {
        auto* myApplication = dynamic_cast<MyApplication*>(JUCEApplication::getInstance());
        jassert (myApplication);
        return myApplications->getSettings();
    }
}

// anywhere now:
Settings::getSettings().getProperty (/* yada yada */);

Simple, secure, no additional statics :wink:

2 Likes