[SOLVED] Set BaseLink in a custom thread
On 13/04/2018 at 01:57, xxxxxxxx wrote:
Cinema 4D Version: R18
Platform: Windows ;
Language(s) : C++ ;
I've got a huge problem dealing with BaseLink data and I was wondering if you could help me.
First of all, I'm aware of that I should never keep direct pointers to hierarchy objects or materials and that I should always refer to them via BaseLinks.
I have to deal with a weird bug in which I have 2 base links, I set them with the exact same pointer (hierarchy object) and after a couple of ctrl-z and ctrl-y on that object, one of these base links give me a NULL pointer, while the other contains the correct updated pointer in the hierarchy.
I assume the problem here is that I set the base links in a custom thread. How safe is that ?
On 16/04/2018 at 10:15, xxxxxxxx wrote:
this is a bit difficult to answer. Can you please describe the situation in a bit more detail? What type of plugin? How/when/In which thread is the BaseLink set? How/when/In which thread(s) is the BaseLink read? What are the document contexts in these situations? Does the use of ForceGetLink() make any difference (if so, please don't see it as fix, but rather some additional info for discussion with us)?
On 17/04/2018 at 01:23, xxxxxxxx wrote:
The two BaseLinks are set in the main thread and they are read in the custom thread.
They point to the same BaseMaterial based on MaterialData plugin.
The document contains a Cloner with a random effector. The cloner has a polygon as child and the polygon has the above material.
The material contains a mograph color shader.
I render the above scene in my render engine and at some point I clear the mograph shader and I start playing with ctrl-z and ctrl-y.
That causes of course the material pointer to change and there is a time in the custom thread (where I read the base links) that one of these baselinks return NULL.
Thank you for your time.
On 18/04/2018 at 09:24, xxxxxxxx wrote:
unfortunately I need to ask you for a bit of patience. I try to get back to you as soon as possible. Sorry!
In the meantime can you maybe do the quick test with checking the result of ForceGetLink(), when GetLink() delivers nulltpr?
On 19/04/2018 at 03:04, xxxxxxxx wrote:
ForceGetLink returns the pointer of the material. The 2 base links have 2 different pointers even though they are supposed to point in the same material.
I assume my mistake is that I read the baselinks in the custom thread, while somehow it is set in the main thread.
Thank you !
On 23/04/2018 at 05:37, xxxxxxxx wrote:
my apologies again for taking so long to focus on this thread. Sorry.
Actually the problem is not so much where you set a BaseLink. Cinema 4D constantly updates and changes BaseLinks, when entities get copied or moved around (see AliasTrans, BaseLink manual and C4DAtom manual). These operations are not atomic, so when reading a BaseLink from a asynchronous thread, you will sooner or later get an intermediate state. The only real option you have is not to... or to prepare the code to deal with the situation. At least there are no locks or anything you could use to protect yourself.
One way to deal with this could be to resolve all BaseLinks before your thread starts running, so it works on copies of the actual data.
I'm wondering, don't you have similar issues with other entities, not only BaseLinks? I mean for example with the materials themselves. I could imagine the user editing a material (maybe adding shaders) and an asynchronous thread accesses the material while in the middle of the process. I could imagine quite a few intermediate states, you wouldn't want to catch with the thread.
On 23/04/2018 at 07:00, xxxxxxxx wrote:
Hello Andreas !
In 99% of the cases I handle the original objects before custom thread runs, while I use cloned objects inside the thread. It appears that I have to do that with everything since what you describe will definitely cause a crash at some point.
Thank you very much Andreas !