Instance variables static or not?
-
Hi there,
I am working on an ObjectData derived plugin and can't seem to decide whether to make my private instance variables - simple structs really - static or not.
So, would
struct MyPluginParameters { Float a; Int32 b; Int32 c; Bool d; Bool e; }; struct MyPluginState { Float f; Bool g; Int32 h; Int32 i; }; class MyPlugin : public ObjectData { public: virtual Bool Init(GeListNode* node); virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh); virtual Bool Message(GeListNode* node, Int32 type, void* t_data); static NodeData* Alloc() { return NewObjClear(MyPlugin); } private: static MyPluginParameters params; static MyPluginState state; }; MyPluginParameters MyPlugin::params; MyPluginState MyPlugin::state;
be preferred to the simpler:
class MyPlugin : public ObjectData { public: virtual Bool Init(GeListNode* node); virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh); virtual Bool Message(GeListNode* node, Int32 type, void* t_data); static NodeData* Alloc() { return NewObjClear(MyPlugin); } private: MyPluginParameters params; MyPluginState state; };
or not? Is there any pragmatic difference between the two options?
Thank you very much.
-
Hello @wnoyce,
Thank you for reaching out to us. Unfortunately, your question is off topic for the forum you have posted in. Please check Forum and Support Guidelines: Forum Structure for an overview of the scope of the different forums.
In general, we do not provide support on language features itself or third-party libraries. I therefore have moved your posting to the off-topic forum.
Regarding your Posting
I am not quite sure how your question is meant; you might want to have a look at static members in the C++ reference. But, yes, there is a fundamental difference between these two options.
static MyPluginState state
would be class bound, i.e., all instances ofMyPlugin
would share the samestate
.MyPluginState state
on the other hand is instance bound, i.e., you need an instance ofMyPlugin
to access it such asmyPluginInstance.state
. Thestatic
variant is always accessed over the class interface, i.e.,MyPlugin::state
.What to do here depends on what you want to achieve with your plugin. Generally speaking, it seems unlikely that you want a static
state
. You should also be careful with field members onNodeData
types, as you can easily produce access violations when you write them from methods which are executed in parallel, e.g.,ObjectData::GetVirtualObjects
. For instance bound members you are usually somewhat safe, but a class boundMyPluginState
would be effectively a global variable shared by all your plugin instances. You will need for sure a signal object here to regulate access. Cinema 4D has multiple mutex/lock/semaphore like objects, most of them are described here. In practice it could look like this (untested pseudo-code):class Foo { private: // A global state object used by all Foo instances and a global lock regulating access to it. static State g_state; static maxon::Spinlock g_state_lock; public: // A method which tries to manipulate g_state. static void Bar() { // When we are not on the main thread, we lock g_state before we start modyfing it. This will // effectively sequentialize threads executed in parallel. When you do this for example inside // a ObjectData::GetVirtualObjects impl., you will sequentialize the cache building of your // plugin. Which is of course quite slow when a user has multiple instances of your object in // a scene. if (!GeIsmainThread()) { maxon::ScopedLock guard (g_state_lock); Foo::g_state.ChangeData(); } // When we are on the main thread we do not need a lock, because the main thread is sequential // in nature on its own. else { Foo::g_state.ChangeData(); } } }
In our API is also the concept of atomic types, which are inherently thread safe. They are however as their name implies limited to atomic data types. Internally, these types are also just a data field with a lock arround it, but they are much more optimized and faster than a normal signal object.
Cheers,
Ferdinand -
-
Hi @ferdinand,
Thank you for moving this topic to its correct category.
Although I believe we agree on the C++ meaning of static members I really wasn't aware that the use of static plugin parameters and static plugin state could in practice be as problematic as you describe and will certainly heed your advice to no longer use static plugin state.
Also, your point on field members and parallel execution of member functions is well taken.Thanks again!