lua-users home
lua-l archive

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


On Thu, Aug 20, 2015 at 6:55 PM, Philipp Janda <siffiejoe@gmx.net> wrote:
> Am 21.08.2015 um 03:27 schröbte William Ahern:
>
>> On Fri, Aug 21, 2015 at 12:55:46AM +0200, Philipp Janda wrote:
>>>
>>> Am 21.08.2015 um 00:21 schröbte Rena:
>>>>
>>>> On Aug 20, 2015 6:05 PM, "Roberto Ierusalimschy"
>>>> <roberto@inf.puc-rio.br>
>>>> wrote:
>>>>>
>>>>> if we want to put some extra bits in
>>>>> 'TValue' to good use and solve the OP problem, maybe a better idea
>>>>> would
>>>>> be to introduce metatables for light userdata.
>>>>
>>>>
>>>> That would be excellent. I find it difficult to find much real use for
>>>> light userdata with only a single global metatable.
>>>
>>>
>>> That would be another welcome feature, but lightuserdata pointing into
>>> full
>>> userdata is unsafe: the full userdata could be collected without the
>>> lightuserdata realizing/preventing that.
>>
>>
>> You wouldn't do that. You would store the reference to the full userdata
>> in
>> the metatable, not as the lightuserdata value. The lightuserdata would
>> only
>> contain the offset. That would require only one unique metatable per full
>> userdata, not per lightuserdata proxy.
>>
>
> That depends. If you have something like
>
>     typedef struct {
>       B b1;
>       B b2;
>       B b3;
>     } A;
>
>     a1 = newuserdata( sizeof( A ) );
>     a2 = newuserdata( sizeof( A ) );
>
> then you can reuse the same metatable for a1.b1, a1.b2, and a1.b3, but
> you'll need a different metatable for a2.b1, a2.b2, and a2.b2. Also you'll
> have trouble passing a1.b1 and a2.b1 to a function unless you invent a new
> way to typecheck arguments (they have different metatables, so something
> `luaL_checkudata` is out of the question).

That's actually pretty easy -- if they're offsets, then their numeric
value represents their type. If they're pointers, then their numeric
value minus the numeric value of the userdata itself represents their
type. You can't do this from the Lua side but the C function to do so
would be pretty trivial.

And if you go with one of the various user-defined type schemes
discussed on this list, you could include a __type() function on the
metatable that would be able to do this and return a nice friendly
string.

> If you have something like
>
>     typedef struct {
>       D d;
>       E e;
>       F f;
>     } C;
>
>     c1 = newuserdata( sizeof( C ) );
>     c2 = newuserdata( sizeof( C ) );
>
> you'd need a separate metatable for all c1.d, c1.e, c1.f, c2.d, c2.e, and
> c2.f. Basically, you would allocate a new metatable instead of a userdata
> for every `__index` operation.

You wouldn't need to allocate a metatable for d, e, and f. The backend
code would be able to say "Oh, this lightuserdata points to a userdata
of type C and we're expecting an object of type E. But the offset says
we can (or can't) cast the pointer to E safely."

Basically it's RTTI.

/s/ Adam