lua-users home
lua-l archive

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


On Jun 1, 2013, at 7:50 PM, Jay Carlson <nop@nop.com> wrote:
> 
> Yeah, with mutable data, this game is over. One way of looking at the shallow_copy() optimization is that it works because we know that anything taking the fastpath is never written to again, so we don't have to worry about not issuing a new identity for it. But that is a little like saying the parrot will not move again because it's nailed to the perch.
> 
Actually as I noted it's not that hard to do a "poor mans" copy-on-write in Lua:

-- Simple copy-on-write for tables (demo). Use newcow() to convert a
-- regular table to a COW table, or to clone a COW table. Regular tables
-- should have one reference only. Note that this could be made safer by
-- having newcow() convert the existing table to a COW and create the
-- shadow table, but this would involve the very copy we are trying to avoid.

do
local cowmeta = {
	__index = function(t, k) return t._shadow[k] end,
	__newindex = function(t, k, v)
		for kc, vc in pairs(t._shadow) do rawset(t, kc, vc) end
		setmetatable(t, nil)._shadow = nil
		rawset(t, k, v)
	end
}

--//// newcow(): Convert regular table to COW table
-- t			Table to convert (or existing COW to make a clone)
-- returns		COW table (or clone of COW table)
function newcow(t)
	return setmetatable({ _shadow = (getmetatable(t) == cowmeta) and (t._shadow) or (t)}, cowmeta)
end
end

t1 = newcow{ a=1, b=2, c=3 }
t2 = newcow(t1)
print(t1.a, t2.a)
t1.a = 10			-- Clone happens here (copy-on-write)
print(t1.a, t2.a)

This code is far from perfect, for example it requires that you don't try to bypass the COW table references (this can be fixed by making newcow() convert the existing table in-place to a COW, but that would requires the shallow copy we're trying to avoid). However, it DOES meet the needs of the original poster, which is to allow a function that does not clone tables where that is not necessary.

--Tim