On 23/07/13 02:51, Carsten Haitzler (The Rasterman) wrote:
> On Mon, 22 Jul 2013 17:30:17 +0100 Tom Hacohen <[email protected]> said:
>
>> On 21/07/13 14:18, Jérémy Zurcher wrote:
>>> Hello from my holiday in France (for the frenchies who know lofofora ;)
>>>
>>> On Friday 12 July 2013  15:42, Carsten Haitzler wrote :
>>>> On Mon, 08 Jul 2013 18:00:15 +0100 Tom Hacohen <[email protected]>
>>>> said:
>>>>
>>>> ok. looked at eo2test.c
>>>>
>>>>      eo2_do(obj,
>>>>            a = inst_func(eo_o, 32);
>>>>            inst_func(eo_o, 10);
>>>>            b = inst_func(eo_o, 50);
>>>>            );
>>>>
>>>> first... passing in eo_o... should probably go away. ie
>>>>
>>>>      eo2_do(obj,
>>>>            a = inst_func(32);
>>>>            inst_func(10);
>>>>            b = inst_func(50);
>>>>            );
>>>
>>> the declaration is
>>> EAPI int inst_func_set(eo2_a, int a, int b);
>>>
>>> expanded to
>>> EAPI int inst_func_set( _Eo *obj, Eo *objid, int a, int b);
>>>
>>> what I first proposed was using a second macro
>>>       eo2_do(obj,
>>>             sum = eo_call(inst_func_set, 32, 12);
>>>             a = eo_call(inst_func_get_a);
>>>             );
>>>
>>> would it be better ?
>>> (Tom, I don't love it, that's just handy ;)
>>
>> I don't like it because it doesn't look like c code any more. This means
>> that what Carsten is asking for can't be done.
>
> of course it looks like c. it just is not c that you are used to seeing. if we
> "make it look like c"  (that is the plain simple funca(x); funcb(x, y); funcc
> (x, y, z);), then we can't really do eo at all. you're SOL. we NEED to be able
> to.
>
> 1. begin a block of operations by dereferencing the objid to a ptr AND ref()
> the obj.
> 2. allow N operations to work on the currently bound "context" object ptr 
> after
> lookup/checks
> 3. when all of #2 are done, unref the obj again.
>
> we need this to compensate for objid indirection. amortizing the cost is part
> of the premise of doing eo. objid's are an absolute must for many reasons
> already explained. you know them as well as i do.

You got me wrong. I was talking about the eo_call(inst_func_get_a) 
convention which I don't like. Anyhow, Gustavo suggested a nice idea 
that I've sent in another email on this thread, take a look, I think it 
can do everything we need.

>
> so as i see it.. your choice is - forget eo entirely, or live with the fact
> that it introduces a usage of c that looks odd to you. you'll get used to it.
> the varargs solution means the compiler disallows arbitrary code in the block
> and makes it much safer - you can't shoot yourself in the foot as easily 
> (don't
> think you, or me - think someone new to efl who sees how to do this and then
> starts thinking they can do if (method(x)) return; etc. etc. - they wont read
> docs telling them they can't do this. it will be an obvious next step to 
> them).
> if you do it the eo2 way you need to somehow try to alert the user to NOT do
> this. if you use nested do{}while(0);s then you can use ONLY break (or 
> continue
> actually), but not return. i can't think of a way of erroring out or warning a
> user that return is disallowed within this block.
>

Told you, I have a solution for that. We can just pass them as 
parameters to a function we are calling that does nothing and is just 
static inline. So the func declaration will be:
static inline void bla(void *a, ...)
{
}

and in the macro we'll do:

<code>
do {
__VA_ARGS__ // (like we do now)
} while (0);
if (0)
        bla(__VA_ARGS__) // this will do the checking for us.
</code>

we can't just do the bla thing because parameter evaluation order is not 
defined in the standard.

>>>
>>>> secondly, having a = xxxx; with ; too.. is going to start encouraging
>>>> people to do really bad things like:
>>>>
>>>>      eo2_do(obj,
>>>>            if (inst_func(32) != 22) return;
>>>>            inst_func(10);
>>>>            b = inst_func(50);
>>>>            );
>>>>
>>>> and all sorts of hell is going to break loose here. i don't believe that
>>>> as a result of returns we can now sensibly handle method errors from an
>>>> eo_do() batch. if we are using returns for errors we SHOULD have something
>>>> like:
>>>
>>> well the rule is really simple to document and explain:
>>>     use break not return in e eo2_do() construct
>>
>> It's better to have enforcement by the compiler.
>
> i agree. in that respect varargs are better. the macros do typechecking and 
> arg
> count checks so we are essentially ok unless you KNOW its varargs underneath
> and bypass the method macros. this requires much more understanding and 
> reading
> of docs/headers so i'd guess this is ok.
>
>>>
>>>>
>>>> Eo_Err err;
>>>>
>>>> err = eo_do(obj,
>>>>               a = inst_func(32);
>>>>               inst_func(10);
>>>>               b = inst_func(50);
>>>>               );
>>>> if (err.error == inst_func1_id) return; // inst_func1 method id is what
>>>> failed
>>>
>>> we have no more function id in the latest prototype,
>>> but this disallow EAPI static inline func();
>>>
>>> I'm waiting for comments from Tom and others about this.
>>>
>>>> if (err.failedop == 2) return; // in a batch, operations are counted, 0,
>>>> 1, 2 // so op id 2 (last one) failed here
>>>> if (err.type == EO_ERR_INVALID_VALUE) return; // can put err inside a type
>>>> field.
>>>>
>>>> note that this is using an error return as a struct, not a basic type (int,
>>>> pointer, char, etc.), and this is perfectly valid and correct in basic c.
>>>> it's not an extension. we COULD pass in a ptr to the err struct too
>>>> instead of using a return.
>>>>
>>>> but... in the end the error is returned and deal with OUTSIDE of the eo_do
>>>> () block. so we guarantee to always exit the eo_do() block at the end
>>>> safely and handle refcounts properly. if people start putting arbitrary
>>>> code inside the block with returns and what not.. compilers will allow
>>>> this in eo2... and we will have problems. big ones. i can smell it right
>>>> now. so i'd say dont allow ; s and arbitrary code inside. use , i.e.
>>>>
>>>> Eo_Err err;
>>>>
>>>> err = eo_do(obj,
>>>>               a = inst_func(32),
>>>>               inst_func(10),
>>>>               b = inst_func(50),
>>>>               );
>>>>
>>>> ... needs some looking into maybe ...
>>>
>>> what does 'guarantee' and 'don't allow' mean ? I think no more than words
>>> in an API doc. if users want to try wrong construction they still will be
>>> able to. (sure eo_do() is stronger in that case, compiler does not accept
>>> code in varargs !!)
>>
>> We can always have a mock static inline function that will get optimised
>> out that is passed all the parameters so we will be able to enforce that
>> no code is allowed there.
>
> example? then u can't do a = method();... and we are back to varargs?

Example above.

>
>>> So what matters is which one is the simplest to use and to document.
>>> for me it's clearly 'do not use return' btw what users and us will do is
>>> not much than eo2_do(obj,
>>>           ret = eo_call(do_some, 133, 254);
>>>           if(!eo_call(try_this,435)) break;
>>>           ret = eo_call(all_perfect);
>>>           );
>>>
>>> no need to explain users how to handle the error code, no need for us to
>>> waste precious time checking last call status to know if we must break
>>> eo2_do(…)
>>>
>>>>
>>>> my other reservation is that e are exposing the pointer to an eo obj TO the
>>>> application code.. and the objid stuff in eo was to try isolate this. this
>>>> now leaks it out into the app... allowing for abuse and misuse. that is a
>>>> downside of this.
>>>
>>> yes, I too dislike this, but don't think this is that harmfull.
>>> it's an opaque type, what could users do with it, free it ??
>>> bloody bastards may the gods punish them I'would say!
>>
>> I agree.
>
> i am more thinking that the value has leaked out onto their stack frame at
> all... it's made its way to the other side of the "firewall"

I see what you mean. Solved in the other mail.
>
>>>
>>> btw I tried to use an object context instead, see devs/jeyzu/eo2
>>> it looks like this (eo2_do() expanded):
>>>     ctx = eo2_do_start(obj_id);
>>>     my_eapi_func(ctx, args);
>>>     ...
>>>     eo2_do_end(ctx);
>>>
>>> the goodies are:
>>>     - no more object pointer leaking in user land
>>>     - detect a missing eo2_do_end() on the next call to eo2_do_start()
>>>     - cache the object data pointer
>>>
>>> ctx is not thread safe but could be
>>
>> ctx has to be defined locally (and thus not thread safe anyway), because
>> you may have a lot of eo2_do inside each other.
>
> yup. thus the local objptr solution with the macroderef (or a func that fills
> in the objptr or local ctx struct - same thing in the end).
>

--
Tom.



------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to