[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: setfenv on userdata
- From: Chris Marrin <chris@...>
- Date: Wed, 24 Aug 2005 16:17:55 -0700
Rici Lake wrote:
...
Why does a userdata have an environment? ...
Thanks. I will look at the code. After all this discussion I was
thinking about this whole structure. My objects look like this:
object --> userdata
-> common metatable
-> c++ instance
-> lua table
-> userdata backpointer
-> prototype
prototype --> userdata
-> common metatable
-> c++ instance
-> lua table
-> userdata backpointer
-> prototype...
So, to Lua the object is a userdata. All objects (userdatas) in my
system have a common metatable which overrides every metamethod. This
looks pretty much like all the other incarnations of object systems on
Lua I have seen. The only unique thing is the notion of a prototype
delegation model, ala Javascript. The __index method first looks in the
instance's table and if it doesn't find it there it looks in the
prototype, and so on.
Naturally the "environment" we have been discussing here takes the place
of my table. This is nice because my table is actually referenced in the
registry and I just hold the ref id in my c++ instance. Whenever I need
the table I have to get the reference out of the registry. I bet using
ENVIRONINDEX is faster, so that is good.
But it occurs to me that this is kind of backwards. I could just put my
c++ instance in the table as a lightuserdata property. I don't because
that would be more expensive to access. Also, I need to hook EVERY
property set call. And if I put a property into the table, the next time
I set it __newindex would not get called.
So, for supporting a c++ bridge, it seems like the right solution would
be to add a void* to table and give access methods to it. That would
solve the access efficiency problem. And I have seen a patch which hooks
all sets to a table, not just new ones, which would solve the second
problem. The I could get by without a userdata.
Taking this one step further, it's not hard to imagine this new pointer
having some structure. Imagine it being a structure containing
lua_Cfunction pointers for all the metamethods, plus a pointer to a
void*. You would check this table first when checking for a specific
metamethod and call it if found. This would solve the biggest overhead
in my app, which is the time spent finding and calling metamethods.
Maybe that last bit is going too far. But if the purpose of userdata
environments is to support c++ interfacing, it seems like the table is
the right place for that.
--
chris marrin ,""$,
chris@marrin.com b` $ ,,.
(650) 941-9040 mP b' , 1$'
M1 ,.` ,b` ,` :$$'
,|` mP ,` ,mm
,b" b" ,` ,mm m$$ ,m ,`P$$
m$` ,b` .` ,mm ,'|$P ,|"1$` ,b$P ,` :$1
b$` ,$: :,`` |$$ ,` $$` ,|` ,$$,,`"$$ .` :$|
b$| _m$`,:` :$1 ,` ,$Pm|` ` :$$,..;"' |$:
P$b, _;b$$b$1" |$$ ,` ,$$" ``' $$
```"```'" `"` `""` ""` ,P`
"As a general rule,don't solve puzzles that open portals to Hell"'