Sending variable-size lists of t_atoms using linklists

$adam's icon

Hi list,

I'd like to write a function that send a variable size array of t_atoms to an outlet, but I'm not sure how to do it. My first guess was to create a t_linklist, create the t_atoms with atom_alloc(), add these atoms to the linked list, send the content of the linked list to an outlet_anything(), (then if needed -- I'm not sure this is necessary -- free the t_atoms of the linked list), and finally free the linked list.

But before doing this, I need to clarify some questions.

The most important is: do I really need to free the atoms after sending them to the outlet? If not... How would they be removed from the memory after they are no longer needed? Do I have to register them with some core function?

Or when I free the linklist, will it free automatically all the t_atoms as well?

The other question: is there a straightforward way to extract the contents of a linked list in an argc-argv way? Or is this something I need to take care myself?

I'd also be interested if is there some better way to achieve what I want to do.

Thank you,
Adam

Timothy Place's icon

By default t_linklist will assume that everything you add to the list is a t_object*. So this means that when you call a method like linklist_clear() that the linklist is going to try and call object_free() on every item in the list -- not what you want in this case. Furthermore, just calling object_free() on the linklist will result in an internal call to linklist_clear(), so there is no avoiding the issue.

One solution is to free the object using linklist_chuck() instead of object_free() and to linklist_chuckptr() etc. to remove items from the list. Another solution to use linklist_flags() to configure the t_linklist to behave differently. For example, you can set a flag to tell it to not mess with your pointers, or you can tell it to automagically call sysmem_freeptr() on the list members when they are removed from the list.

As to whether you need to free your atoms, how are they allocated? If they are allocated dynamically, then you will need to free them. If you allocate them using sysmem_newptr() then you can allow the linklist to free them for you (as just mentioned) or you can free them yourself.

Cheers

Peter Castine's icon

I'm assuming you want to use your list of atoms with somthing like outlet_list().

Typically objects with methods creating lists to be passed to outlet_list() work with a fixed-size array of t_atoms on the stack (bear with me, I'm getting to your question!)

This assumption has a consequence for any object that receives an array of Atoms in a 'list' message: if it wants to keep the Atoms for use after receiving them, it must make its own local copy.

As a result, if you want to dynamically allocate variable size arrays of Atoms in a method, the basic structure is

{
int myAtomCount;
t_atom* myAtoms;

- calculate value of myAtomCount
- allocate myAtomCount Atoms and assign address to myAtoms
- initialize content of myAtoms

outlet_list(myOutlet, NIL, myAtomCount, myAtoms);

- free myAtoms
}
// Untested Web Pseudo-code

You can use getbytes(), malloc(), sysmem_newptr(), or whatever your favorite poison is for allocation. Of course you must use the matching free function.

I do not think you want to use a t_linklist with outlet_list(), although there might be some devious reason to want to do so.

Hope this helps,
Peter

$adam's icon

Sorry for the late answer, I was offline for a while.

The assumption was right, I wanted to send the list with outlet_list().

Thanks for all the help of both of you, now the thing works.

The only thing that took me some time was finding out the way to export the contents of the linklist of atoms to an array of atoms that outlet_list() understood (since outlet_list expects t_atom * and linklist_makearray exports t_atom **, so one needs to create a new temporary array and clone the list exported by linklist_makearray to guarantee that the t_atoms are one-after-the-other in the memory). (Unfortunately I couldn't eliminate the linklist since the code creating the output is quite sophisticated.)

Thanks again.