[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: CONSTANTS patch - LKBIT
- From: Nilson <nilson.brazil@...>
- Date: Tue, 28 Sep 2010 04:17:55 -0300
On Tue, Sep 28, 2010 at 2:29 AM, Juris Kalnins <juris@mt.lv> wrote:
> What exactly are the semantics of the functions that you propose?
When a value stored inside a field is locked, the value of the field
cannot be changed, what simulates a constant behavior.
> What is the intended use of such feature?
Protect constants values from accidental or malicious changes, like in
any other programming language with constants.
>> myprint = function(...) print('Hi',...) end
>> _G.print = lkset(_G.print) -- protects against accidental change
>> _G.print = myprint
>>>>>
>>>>> error: attempt to change a locked value: function: 004755D8
>
> so what exactly gets locked -- value of function 'print' or value
> at the key 'print' in table _G?
What is locked is the value stored inside _G.print field.
> local a = lkset({}) -- is a locked?
Yes. The value stored in a cannot be changed.
So a = nil will fail, but a.test = 1 is ok.
> local b = { k = a } -- is b.k locked?
No.
For your understanding, I must tell the implementation details - no secrets:
The LKBit are in fact 2 bits that represents:
00 - UNLOCKED, 01 - LOCK, 10 - LOCKED, 11 - UNLOCK.
When you assign a field with a LOCKED value, the patch changes the
bits to 00 - UNLOCKED before store it. The function lkset() sets the
bits to 01 - LOCK. When you assign a LOCK value to a field:
1) if the field is UNLOCKED, it becomes LOCKED
2) if the field is LOCKED, then << 2 options - I will decide later>>
a) error "change a locked..." - this option is the usual constant behavior.
b) if the new and old values are equal then ok else fail - this option
makes lkset idempotent.
> local c, d = {}, {}
> c.k = {}
> d.k = c.k
> c.k = lkset(c.k) -- is d.k locked now?
No. Although both references the same object, each one has its own
storage area.
The patch will lock this area.
> c.k.v = 1 -- does this work?
Yes.
--- UNFINISHED IDEA BEGIN ---
But I was working in a new version of original message adding the function:
const(value, optional_deep) <==> lkset(value, true) plus an optional_deep
that makes all the elements inside the table (tree?), constant.
So to make c.k a read-only table, you should write:
c.k = const(c.k,true)
It is not finish because it is too dangerous.
If the table c.k references a outer table, like _G, it will damage the
whole LuaState.
May be a const(value,deep_level) to control how deep the const will be
applied...
true means total
0/false/nil means don't apply inside
1 or more is the deep level
May be testing if any references reachs _G
.
Note that you still could add new items inside the table.
The table itself is not locked. Just the values stored inside when you
called the const()
--- UNFINISHED IDEA END ---
> setmetatable(c.k, evil_metatable) -- does this work?
Yes for now.
--- UNFINISHED IDEA BEGIN ---
I didn't think about that yet.
Perhaps a convenience parameter in const that makes __metatable = false.
const(tab,deep_level,lock_metatable)
--- UNFINISHED IDEA END ---
-----------------------------------------
Someone would like to help?
A good knowledge of table implementation in Lua will shorten the work.
A environment ready to make lots of benchmarks to measure the impact
on regular Lua code will help too.
--
Nilson