lua-users home
lua-l archive

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


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"'