On 10/4/06, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:

On 04.10.2006, at 15:52, Stephen Deasey wrote:
>
> Hmm...  I think this does work. Here's how I read it:

First time arround, there will be 3 lookups.
The next round should be simple deref.
Allright this might compute. If you have this in a proc
body the "themutex" will be a literal objects and will/should
last "longer".


Not just proc bodies, but also sourced files and looping commands. You
have to go out of your way to evaluate a piece of Tcl code and not
have it compiled to byte code. Like use the nscp control port... :-)


I did it under the debugger in the nscp session and every
time I get another object as "themutex". This is most probably
because the code does not compile into bytecodes...

OK. I can accept that. Still, you put this into frequently
called procedure and there you go (literals are freed AFAIK,
when procedure scope is exited): again you have global locking.


I'm not sure what you're saying here. What is freed, and when?


>
>> If one however does:
>>
>>   set m themutex
>>   set t thecond
>>
>>    ns_mutex lock $m
>>    while {} {
>>       ns_cond wait $c $m
>>    }
>>    ns_mutex unlock $m
>>
>> it WILL work. But how are you going to convey this information
>> to the Tcl programmer??? He's implicitly serializing his app
>> at the place he does not expect (lookup of the internal hash
>> table).
>
>
> Actually, the above might NOT work... :-)

The first two init lines I havent counted for. It is just the
remaining and in fact most specifically the
    ns_cond wait
that was the problem as it may awake and sleep again.

>
> But I'm having a hard time coming up with real world scenarios where
> that might happen...

This is OK. In the compiled code, things start to look somehow
different.
But also when you use the "themutex" to put it in the nsv array
you loose the caching effect of the object.


Right. But why would you ever do this? This was a corner case example
I gave to show that it *could* happen, if you tried real hard and
looked at it funny, but you wouldn't actually do this, right?


Unlike with handles
where you get the "real thing" immediately and need not global
lock.


In the case of the thread objects this is the case, but they are
special (or weird). The internal rep of a thread object (mutex, cond
var etc.) is a serialised C pointer. Given the string you can
re-create the pointer (and if you try hard enough you can create an
invalid pointer and crash the server, hence weird).

But for handles in general, such as nsproxy, this is not the case.

Remember, if you can refer to thread objects by name then you don't
*need* to put the name in an nsv array, for example. And if you do,
ns_mutex create does in fact still return a handle.


Keeping the handles "away" from the user, means you need to manage
handles yourself because the underlying C code needs handles/pointers.
Every time you do that, you need to lock. In this case the global lock.


But you don't. That's the point. If this isn't the case, then I've
done something wrong and the code needs to be reverted.


So, nothing is for free. By allowing the tcl programmer some freedom,
you charge him with some performance/concurrency.

The best illustration:

lexxsrv:nscp 7> ns_mutex unlock themutex
Connection closed by foreign host.

Here no check is done: you get a core. But if the themutex was
locked before, all would be fine.


I guess this is a good example of trade offs -- performance over
safety. But it's not a good example of the differences between names
and handles, because you can do exactly the same thing:

   % set m [ns_mutex create]
   t0xfd3dd9 a0xa654800 ns:mutex
   % ns_mutex unlock $m

The trade off here is balanced, you can have one thing (safety) or you
can have the other (performance). Your choice. For both handles and
names.

On the other hand, the choice between names and handles is not
balanced. Assuming names actually work (you've sort of said they don't
above), they are equally as fast. So the choice is fast and easy or
fast and hard.

Fast and easy, please!

There's also the question of whether names allow the same kind of
expressive power as handles, in the nsproxy case for example. I think
they are, but that's another thread.


In the Tcl threading extension I check mutex for a locked state
and TCL_ERROR if lock was attempted on an already locked mutex
OR an attempt was made to unlock never-locked mutex.
This requires lots of low-level plumbing BUT it gives the Tcl
coder maximum comfort.

Neither way is "right" or "wrong".  So you can't generally
"avoid" using handles as this will lead you to situation
where you must sacrify some speed/concurrency for getting
the comfortable API.

Reply via email to