Vuo
0.3
|
When a node allocates data on the heap (for example, with malloc
) and sends it through an output port, the data travels to other nodes. The other nodes can hold onto that data for any amount of time. There's no guarantee of which node will be the last to use the data. Who is responsible for deallocating that data?
The answer is that the Vuo runtime is responsible for deallocating the data – but port type and node class definitions are responsible for informing the Vuo runtime about the data.
The Vuo runtime uses reference counting to keep track of heap-allocated memory and deallocate it when all nodes are finished using it. The Vuo API for node classes and port types provides three functions for reference counting:
vuoRegister(void *, void(deallocate *)(void *))
informs the Vuo runtime that the data should be reference counted. This function should be called once for each heap-allocated data item that's sent through an output port or stored in node instance data. When the reference count of a data item is decremented to zero (its original value), the deallocate
function is called on the data item.vuoRetain(void *)
increments the data item's reference count, informing the Vuo runtime that someone has started using the data. The vuoRegister
function must be called on a data item before the first call to vuoRetain
.vuoRelease(void *)
decrements the data item's reference count, informing the Vuo runtime that someone has finished using the data. The vuoRetain
function must have been called at least N times on a data item before the Nth call to vuoRelease
.To make the reference-counting system easier for you to use, the Vuo compiler automatically inserts many of the necessary calls to vuoRegister
, vuoRetain
, and vuoRelease
. If you're implementing a stateless node class, you never need to call these functions. If you're implementing a stateful node class or a port type, read on to learn when to call these functions.
If you define a port type that's a pointer to heap-allocated data, the typeInitWithString
function is responsible for registering that data. For example:
If your port type is a container for heap-allocated elements, then the type definition is responsible for registering each element that's allocated, retaining each element that's added, and releasing each element that's removed. For example:
If you define a stateful node class, and the node instance data is a pointer to heap-allocated data, the node class is responsible for calling vuoRegister
on each instance of the type that's allocated. For example:
If the node instance data is a container for heap-allocated elements, then the node class is responsible for registering each element that's allocated, retaining each element that's added, and releasing each element that's removed. For example: