Jump to content

How to treat nodes ownerships


photo

Recommended Posts

Hello,

Previously (in 2.5) - for my background loading system from my own formats - in background threads or in main loop all I need to do when creating a new node was something like:

engCluster = Unigine::ObjectMeshCluster::create(nullptr);

populate the node data and then when no longer needed (scene was released), just make sure all references to it are removed and the object was deleted as per:

virtual ~NodeInterface() { if(owner) delete obj; }

since owner was always 1.

Now (version 2.9.0.2), based on the new Breaking Changes in API Migration, the ownership of nodes is for the editor (only if engine.editor->isLoaded() returns true, which of course doesn't for me since I am not in the editor). So I end up with objects left in memory (even if node interfaces to them are released since owner is always zero).

Question iswhat is the exact procedure to deal with nodes in background threads or main thread when editor is not loaded? I just want the behaviour like in 2.5 (i allocate them, when references are removed -> nodes are released, objects are released). Will I have to do call node->grab() after each create? Once grabbed, can I assume that the node is correctly released when all references to its pointer are released or I call destroy?

The migration documentation is not very clear what to do in this case (no editor, background threads).

Kind Regards,

Adrian

Link to comment

Hi Adrian,

I just want the behaviour like in 2.5 (i allocate them, when references are removed -> nodes are released, objects are released)
To return to this behavior, you just need to add this lines after node creation:

ObjectMeshClusterPtr engCluster = ObjectMeshCluster::create(); 

Editor::get()->releaseNode(engCluster->getNode());
engCluster->grab();


But, i want to say that our "smart pointers" are not thread safe. The same as Editor::addNode(), Editor::releaseNode() functions.
I recommend to use Unigine::AsyncQueue to loading nodes in background threads. It doesn't put nodes in the Editor.
 

Best regards,
Alexander

Link to comment

Hi Alexander and thank you for your answer.

I know that Unigine smart pointers are not thread safe and I did some measures to avoid issues:

- during streaming they have no parent nodes or their parent nodes don't have parents (or somewhere up in the hierarchy there is one parent with not parents, so their hierarchy is not yet linked to the world)

- parent nodes are set in the final stages of the streaming, when all data is in place, and this is done in the main thread

- I make sure the pointers that are created in background threads are never accessed by other threads than the one streaming, at least not until the final parent nodes are set (in the main thread)

- once I have a hierarchy that is finally constructed, I enable the root node of it, in the main thread, once its parent is also setup. Basically root node was disable up until that point, while child nodes were streamed in.

Let me know if this ensure thread-safety.

Plus, am I right to consider this the thread-safe variant of your code:

		if(Engine::get()->isMainThread() && Editor::get() && Editor::get()->isNode(P->getNode()))
			Editor::get()->releaseNode(P->getNode());
		P->grab();

		where P is the object pointer I want to grab.

Since I want to be able to call this from both a background thread and an worker thread.

I will also have a more closer look to AsyncQueue.

Kind Regards,

Adrian L.

 

Edited by adrian.licuriceanu
Added example how to thread-safely grab pointer
Link to comment

Let me know if this ensure thread-safety.
Yes, it looks like this. AsyncQueue works the same way.

Plus, am I right to consider this the thread-safe variant of your code
Checking the Editor::get() is unnecessary. This is a part of the Engine. It is always exists.

Best regards,
Alexander

  • Like 1
Link to comment
×
×
  • Create New...