SharedResourcePointer

I've just added a new class SharedResourcePointer, which some of you may find handy.

Basically, it's a simple smart-pointer that automatically manages a shared static instance of an object. The interesting bit about it is that it's ref-counted, so that when all of your SharedResourcePointers go out of scope, the shared resource is also freed. That makes it a bit like a singleton, but more dynamic, and it means that your shared object will get deleted before shutdown without using DeletedAtShutdown, or relying on the runtime's statics being deleted.

In particular, this may be a good thing for plugins, where you don't really want to use a static or singleton, but have shared things, e.g. pre-calculated values or shared graphics, which you want to share between instances of your plugin.

1 Like

Nice addition! I think that most of us developing plug-ins already have wrapped their own solution for this kind of topic, it's good that it gets supported by the library now :)

One suggestion, though: as you did for some other such classes, I think that a small code example in the class documentation would greatly help understand what's the intended use for the class

Yes, it's a pattern that I've found myself reinventing multiple times over the years without realising it. Will add a code example when I get a moment, and there are probably quite a few bits of existing code in the library which I'll be able to simplify with it.

*cheers from the crowd*

Very nice! 

And if someone can point me to programming solutions to share initialisation code and resources between plugin instances, I would be very grateful! 

Can you show us an exapmle with a static variable?

There's example code in the class's documentation.

Isn't there a potential alignment issue with this code ? :

static SharedObjectHolder& getSharedObjectHolder() noexcept
    {
        static char holder [sizeof (SharedObjectHolder)] = { 0 };
        return *reinterpret_cast<SharedObjectHolder*> (holder);
    }

 

(since holder is not required to have the alignment needed by the SharedObjectHolder struct)

Why would it matter whether or not it's aligned?

(Though TBH I'd be very surprised if any compiler didn't align a 24-byte static block)

It would cause a crash on CPUs that do not handle word access on non-aligned address (x86 have no problems with that) -- according to http://www.ibm.com/developerworks/library/pa-dalign/ there could also be issues also with the atomical memory access of the spinlock if it is not correctly aligned

 

Hmm. Ok, fair enough, I had forgotten about ARM. Even so, I'm sceptical that any compiler would actually fail to align a block like that, and I vaguely remember hearing that the C++11 spec explicitly says that larger blocks that aren't part of a larger structure should be aligned (I could be wrong about that..). But, since it's easy enough for me to make sure it's aligned, I will do!

Hello everyone,

I am bit lost in using a SharedResourcePointer. Is there any code you have to see how it works between multiple instances of an application or plugin?

Cheers,
Paulo

As far as applications go, there isn’t much about it. Applications running in different processes will have their own instances. It can still be useful if you want your application to have some object that can be accessed everywhere without recreating it each time it is needed. (In the same process.)

With plugins it is more interesting. Each plugin instance will be using the same object when you use it via SharedResourcePointer. You would typically have it as a member of your AudioProcessor subclass. The obvious candidates for use are for example AudioFormatManager and AudioThumbNailCache. But you will need to subclass those, SharedResourcePointer needs the held object to have a default constructor. (AudioFormatManager has a default constructor but you will probably want the used instance to have its registerBasicFormats() method called before use.)

2 Likes

I’m far than being a proper cpp coder but as JUCE switches to c++11, shouldn’t ‘std::shared_ptr’ be enough?

The shared_ptr needs to be created somewhere and you need access to it.
But the SharedResourcePointer will grab the one and only instance out of thin air (similar to a singleton), IIUC. Just with automatic disposal when no reference is held, opposed to the singleton, that will be cleaned up when the app or the plugin is closed.

(just realise, what happens if you use a Singleton in a plugin? probably a bad idea anyway, since statics are problematic)

1 Like

It is a bad idea if one isn’t careful with how they are used, but they can still be useful in some limited cases.

The fear about statics and globals in plugins mostly rose when multicore CPUs happened and the audio processing actually started happening simultaneously from multiple threads. But for example for GUI things, statics and globals likely can be used without too many issues, as long as one realizes each plugin instance will be using the same variables/objects. There should always be a good reason to use globals and statics. For example, convenience of getting access to some desired objects/variables usually isn’t one.

I think the minimum damage they do is that they leak by design. There is no way they are destroyed automatically, only once the host is quit.
So it’s not that anything will crash, when statics are used, but I think it is no mistake to avoid them.

Well, that’s why you want to use SharedResourcePointer and not statics/globals directly… :wink:

Indeed, because the SharedResourcesPointer doesn’t leak, does it?

It doesn’t, it keeps track of the use count of the object, when it goes to zero, it is deleted. If the object is later needed again, it is recreated using the class’s default constructor. The requirement to have the default constructor is a bit annoying and could actually be fixed with some C++11 and later magic, though…