Page MenuHomePhabricator

Unify handling of contents of complex types
Open, HighPublic

Description

Our current approach to handling complex types is inadequate. Based on previous discussion, we've come across this kind of design:

View types

iterator, accessor, slice, etc are "view" types. They can contain any type within their <>, including value types. They never own their "contents" - as they're just views to another piece of memory.

The behavior should be like this:

iterator<Foo> where Foo is a struct/value type:

typedef struct Foo {...} Foo;
Foo *x;
EINA_ITERATOR_FOREACH(itr, x) { ... }

iterator<Foo> where Foo is a class or a pointer-like type:

typedef Eo Foo;
Foo *x;
EINA_ITERATOR_FOREACH(itr, x) { ... }

Note how the fact that Foo is pointer-like does not matter - within this context, the type is always "flat", without resorting to double pointers anywhere.

As ptr() will be removed, it will not be allowed to be within <>, i.e. no explicit pointers inside iterator/accessor body.

Owning types

These are list, array, hash, future

The behavior here will be similar to view types, but we need to do implementation for view types first, once that is done, we can move on to owning types. Examples:

list<Foo> where Foo is a struct/value type:

typedef struct Foo {...} Foo;
Foo *x;
EINA_LIST_FOREACH(list, l, x) { ... }

The idea is that if an owning type contains value data, it implicitly owns said data. Whether the caller needs to take care of freeing those depends on who owns the container itself. For example:

foo {
    return: list<Some_Struct> @owned;
}

For this, the caller of foo will need to do EINA_LIST_FREE on the result, freeing each individual Some_Struct pointer. However, if you do not add @owned, the callee (foo) needs to take care of it, and the user doesn't have to do anything.

For list<Foo> where Foo is a pointer-like type (class, container, etc), the behavior is slightly different. The @owned keyword can be specified within the container itself to inform the generator whether the container owns its data. For example:

foo {
    return: list<Some_Class @owned> @owned;
}

This has effectively identical behavior to the example with a struct, i.e. you need to do this:

Eina_List *x = foo();
Some_Class *o;
EINA_LIST_FREE(x, o) efl_unref(o);

However, if you specify list<Some_Class> @owned, you only need to do this:

Eina_List *x = foo();
eina_list_free(x);

Not specifying ownership on the list<...> means the callee takes care of freeing the container and the API user doesn't have to worry about it. In that case, @owned on the contents usually doesn't mean much for the user, as the callee is responsible for everything about the list.

Just like with view types, explicit ptr() will not be allowed within the body. But this is for *after* view types are handled correctly.

Summary

For now, I will need @lauromoura or @felipealmeida or someone else to take care of the existing generators to adapt to the new behavior for view types. Once that is done, we will do the same for owning types. I will take care of adjusting the syntax bits in eo files and libeolian library.

q66 created this task.Jun 26 2019, 7:24 AM
q66 triaged this task as High priority.

Adding Cedric as this may change how MVVM Models work.