[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Vala] what does # mean in a member method formal parameter?



Yu Feng <rainwoodman gmail com> writes:

> On Fri, 2008-05-09 at 21:16 +0200, Maciej Piechotka wrote:
>> On Fri, May 9, 2008 at 5:52 PM, Yu Feng <rainwoodman gmail com> wrote:
>> >
>> > On Fri, 2008-05-09 at 11:18 +0200, Maciej Piechotka wrote:
>> >> Yu Feng <rainwoodman gmail com> writes:
>> >>
>> >> > what does # mean in a member method formal parameter?
>> >> > Generally, # stands for ownership transfer; But there are some
>> >> > in-consistence. Consider the following two examples:
>> >> >
>> >> >
>> >> > 1. if I write a library by vala:
>> >> >
>> >> > class MyHashTable: Object{
>> >> >   void insert(Object # obj) {
>> >> >     ..
>> >> >   }
>> >> >   static void test {
>> >> >      MyHashTable h;
>> >> >      Object o;
>> >> >      h.insert(o = new Object());
>> >> >   }
>> >> > }
>> >> > I will get
>> >> > MyHashTable_test(){
>> >> >    MyHashTable_insert(g_object_ref(tmp));
>> >> > }
>> >> > and
>> >> > MyHashTable_insert(GObject *o ){
>> >> >    ....
>> >> >    ....
>> >> >    g_object_unref(o);
>> >> > }
>> >> >
>> >> > what happens is during the life time of insert the ownership of 'o' is
>> >> > guarantted to be held in 'h'; then the reference is removed. The total
>> >> > effect is the ownership is not transferred to 'h' at all;
>> >> >
>> >>
>> >> 1. Use generics
>> > This is a piece of example and MyHashTable is a collection of a specific
>> > object.
>> >> 2. Why not reuse the code and use libgee?
>> > Because I am writing a library that don't want to introduce any
>> > dependency except DBus and GLib. In other words, I am writing C code
>> > with the help of vala.
>> >> 3. If you put the object somewhere it also be refed.
>> > I have to explicitly transfer the ownership from the method code block
>> > to the object anyway.
>> >
>> 
>> Eighter I don't understend what you mean or you don't have to.
> The assignment is also an explicit transferring of the ownership.
>> 
>> >>
>> >> void insert(Object #o) {
>> >>      obj = o;
>> >> }
>> >
>> >
>> >>
>> >> will generate:
>> >> GObject* _tmp1;
>> >> GObject* _tmp0;
>> >> g_return_if_fail (self != NULL);
>> >> g_return_if_fail (o == NULL || G_IS_OBJECT (o));
>> >> _tmp1 = NULL;
>> >> _tmp0 = NULL;
>> >> self->obj = (_tmp1 = (_tmp0 = o, (_tmp0 == NULL ? NULL : g_object_ref (_tmp0))), (self->obj == NULL ? NULL : (self->obj = (g_object_unref (self->obj), NULL))), _tmp1);
>> >> (o == NULL ? NULL : (o = (g_object_unref (o), NULL)));
>> >>
>> >> and
>> >> void insert(Object #o) {
>> >>      obj = #o;
>> >> }
>> >>
>> >> will generate:
>> >> GObject* _tmp1;
>> >> GObject* _tmp0;
>> >> g_return_if_fail (self != NULL);
>> >> g_return_if_fail (o == NULL || G_IS_OBJECT (o));
>> >> _tmp1 = NULL;
>> >> _tmp0 = NULL;
>> >> self->obj = (_tmp1 = (_tmp0 = o, o = NULL, _tmp0), (self->obj == NULL ? NULL : (self->obj = (g_object_unref (self->obj), NULL))), _tmp1);
>> >> (o == NULL ? NULL : (o = (g_object_unref (o), NULL)));
>> >>
>> >> (as o == NULL after the assigment the last g_object_unref will never be called).
>> >>
>> > obj = o is kind of confusing. I prefer obj = #o, but it lacks a
>> > detection for the NULLness of self->obj.
>> >
>> 
>> It do not lack. Fragment of line:  self->obj == NULL ? NULL :
>> (self->obj = (g_object_unref (self->obj), NULL))
> Sorry I missed it.
>> 
>> > with a lot of #s, from the caller(invocation) to the callee(formal
>> > parameter, to the code block in the function the ownership of the object
>> > ransfers like:
>> >
>> > 1: the caller code block gives the ownership to the callee by a # in the
>> > invocation.
>> > 2: the callee pass the ownership to the callee body code block;
>> > 3: the callee code block gives the ownership to an object property; or
>> > hold an ownership explicitly by using the .ref() method.
>> >
>> > There are three ownership transfers involved in it, thus three #s shall
>> > be needed.
>> >
>> >> > 2. Now consider the same .vapi, but a route in GLib:
>> >> > GHashTable.insert(#key, #obj);
>> >> >
>> >>
>> >> Do you mean GLib.HashTable? What version of vala are you using?
>> >>
>> > 0.3.1
>> >> > GHashTable h = new GHashTable.full(....,....,g_free, g_object_unref);
>> >> > h.insert("key", o = new Object());
>> >> >
>> >>
>> >> IMHO better (motr type-safe):
>> >> GLib.HashTable<String, Object> h = new HashTable<String, Object>(...);
>> >>
>> >> > the code will be
>> >> > g_hash_table_insert(g_strdup(key)), g_object_ref(o));
>> >> >
>> >> > and 'h' will own 'o' until one removes o from the hash table.
>> >> >
>> >> >
>> >> > The two behaviors are inconsistent.
>> >> >
>> >>
>> >> They are consistent IMHO. They return something, which may be freed
>> >> by hashtable.
>> > Yes, I thought about it last night in the dream. They ARE consistent.
>> > There is still something not so perfect. I had a clear(well defined)
>> > model for the ownership issue and the use of # sign in mind now. I'll
>> > write it somewhere and perhaps vala can adapt it.
>> >
>> 
>> I'm not vala dev so I can't help.
>> 
>> >>
>> >> > I propose to (1) remove the tailing unref code when there is a ownership
>> >> > transfer tag in the declaration;
>> >>
>> >> You may do something like that by:
>> >> h.insert("key2", #o);
>> >>
>> >> o will become null to avoid problems with destruction of hash before time:
>> >> h.insert("key2", #o);
>> >> h = null; // Will call unref and probably destoy table and hence unref all hold
>> >> // objects.
>> >> o.something(); //Oops. It's destroyed...
>> > Still, if you take a look at the generated CCode, there is an
>> > unnecessary un_ref at the end of the code block.
>> >
>> 
>> Well - not exactly. One ref/unref cycle is added to code generated by
>> vala. However we, humans, know it as we have meaning of code in mind.
>> However I cannot imagine how it could be autogenerated without looking
>> into called method (and even then I guess it is not possible).
>
> It is possible. Add a property 'ownership_transferred' to
> FormalParameter(or some other entity for objects), If there is an
> ownership_transferring, mark ownership_transferred = true. If
> ownership_transferred = true and there is another transferring, panic.
>
> At the cleanup stage of the code generator, if the object is transferred
> then skip the unref.
>
>> >>
>> >> > or (2) to completely ignore the # tag,
>> >> > and relies on the programmer to explicitly claim a reference of 'o' by
>> >> > o.ref().
>> >> >
>> >>
>> >> Well - the point of vala is to make things simpler. Managing references is one
>> >> way of doing it.
>> > Thus it seems to be OK to ignore the # sharp sign in the code generator for the formal reference.
>> > Currently If there is a #, the callee will ref the object, and the caller will unref it at the exit.
>> > The total effect is almost the same as without a #. (except some rare case where the object is unrefed during the callee.
>> >
>> 
>> I guess that # for objects are mainly for generics.
>> 
>
> No. # is for ownership, as stated in the vala tutorial.

You misunderstood me. I know what # is for but the cotext in which it is used 
is to make possible writing generice.

Regards

-- 
I've probably left my head... somewhere. Please wait untill I find it.
Homepage (pl_PL): http://uzytkownik.jogger.pl/
(GNU/)Linux User: #425935 (see http://counter.li.org/)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]