Model and ensure value priorities

i m searching for a strong bug in my project, and i think i have found the why, but not the how… I hope the following will be clear for anybody :

  • my model is composed of a scene and a lot of layers, pointing to images

  • my runtime calculate those layers, with some layers animated, and some not, and display them in their supposed order. the animations are calculated inside it, layer per layer

When i m using i m gui to make a layer climbing up or down in my list of layers, i m experiencing strong mismatches, especially with animated images (where there are calculations in memory)

I have the feeling that all the ensure value chain is somehow responsible of thoses mismatches, with disturbances between refreshment of the ensure value process in the model and in the runtime (executing the model order)

So my question is :
How can i stop to refresh my ensure value in the runtime, while im manipulating the model ? Is there any way to know if an ensure value order has been executed, so i can enable my runtime process to be executed without leaks ?

I assume you already understand that immutability is important for EnsureValue nodes (when you use channels).

This is a common problem that I have encountered many times myself. My advice is to avoid using EnsureValue nodes until the very last moment and only use them when you understand that you cannot do without them.

If you have a lot of EnsureValue regions, the following happens: the value (e.g. a model record) changes, then in the next frame this change propagates across the patch and each EnsureValue processes this change. A race occurs.

I would also recommend using Apply pin on the node so that you always know when ‘Ensuring’ occurs in the EnsureValue node.

It is important to understand the difference between EnsureValue and SetValue. The first node will not trigger an ‘event’ or notification in the channel if the value is equal to the previous one. The second will trigger an event or notification in any case.

EnsureValue_Issue.vl (19.7 KB)

1 Like

thank you @yar for those very important advices. Great to know about difference with SetValue !
I m trying to use essentielly Select (by path) but i have many cases, especially in ImGui, where select by path simply doesnt work as expected (something related to deepness of the UI), and where EnsureValue is the only way to have an effectiv result on the model.

@karistouf I have thought about your answer and believe it is right to respond for future generations.

Unfortunately, I do not understand why, in your case, the data cannot be directly connected to the imgui widget nodes. This should not be a problem if the variables in your application model match the types offered by the widget node (e.g., ‘string<->string’ or ‘float<->float’). I have done this many times. Earlier, I wrote that immutability is important in this case. Check that your model is a Record.

But if the data types are different or you want more complex behaviour, you need to use the Merge node (make sure it’s a channel merge). In it, you can choose what to do with the data when it comes from source A and what to do with the data if it comes from source B. There is a version with optional output support that allows you to control whether or not to create an event. The node also supports the ability to control ‘who is the source of truth at initialisation’.

In general, when using the Observable stack (which includes Channel by its nature), I recommend going into runtime (into ‘frame-by-frame work’) only for some good, objective reason, trying to keep the entire event tree exclusively in observable style. VVVV has many tools suitable for this and quite a few advanced techniques.

@yar thank you so much for me and generations :-P
Well i m normally with records, but yes sounds interresting its possible i have steel some classes inside my general record. Thats a super hint.
About also generations it would be super great to have an example on how you would use this channel merge node in a more global structure with differents treatments branched on one model.

Yes, that’s exactly what I’m talking about. I suspected something like that. Why does it work this way? It is important for the channel that the object inside can be tracked for changes. This is done by comparing the state of the object frame by frame. Mutable objects are compared only by reference to the object, and a change will occur only when a new object is created. Accordingly, an event in the channel will only occur when a new object is created. Immutable objects, on the other hand, are automatically ‘reissued’ when any of their values change, and the comparison automatically shows that the object has changed. This is the basic principle of immutability and why it is valued in many architectures.

Here I show how to use merge. I specifically chose a node with optional pins to demonstrate advanced usage, but you can use a ‘regular’ node.

Channel_Merge_Example.vl (24.3 KB)

Thank you @yar ! its super clear !

It means that better than using im gui with operations attached to buttons and to the model inside of imGui, i need to use channel like flags or handlers to to directly in the runtime the specified operations ? did i got it ?

about classes so this means EVERYTHING being Records ? is it right ?

@karistouf I don’t quite understand what you mean, but you can provide a minimal example and I will comment on it.

As for Classes or Records: what matters is what is inside the Channel. The channel contains an object, it will use the ‘what was’ versus ‘what became’ comparison mechanism, every frame. If there is a class instance in the channel, the comparison will be based on a reference to the class instance, which does not change until the object is explicitly recreated (this is the essence of mutability; the object in memory is constant until it is recreated). And if the channel contains an instance of a record, then such an instance is by its nature recreated when changed: each change is not a change in the object’s field, but the creation of a new object with the field that has changed (this is the essence of immutability, the object cannot be changed in memory, its instance is recreated in another place in memory). Therefore, the channel tracks the change ‘automatically’. Immutability is important if it is important for you to generate events in the channel when a change occurs, so the choice of type for the object inside the channel is important. Records in VVVV can contain mutable objects, and if you extract them using select, you will get a channel with a mutable object and will not be able to track its changes as observable events.

Perhaps I should make a disclaimer that I am simplifying things considerably, but if I were to go into all the details, I might lose track of the main point.

@yar excellent ! thank you !
this is agregating in a clear way all points of views i had from this topic. this is a good synthetic definition for newbies ! to keep !