1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
local lanes = require("lanes").configure{ with_timers = false}
local l = lanes.linda "my linda"
-- we will transfer userdata created by this module, so we need to make Lanes aware of it
local dt = lanes.require "deep_test"
local test_deep = true
local test_clonable = true
local test_uvtype = "string"
local nupvals = _VERSION == "Lua 5.4" and 2 or 1
local makeUserValue = function( obj_)
if test_uvtype == "string" then
return "some uservalue"
elseif test_uvtype == "function" then
-- a function that pull the userdata as upvalue
local f = function()
return tostring( obj_)
end
return f
end
end
local printDeep = function( prefix_, obj_, t_)
print( prefix_, obj_)
for uvi = 1, nupvals do
local uservalue = obj_:getuv( 1)
print ( "uv #" .. uvi, uservalue, type( uservalue) == "function" and uservalue() or "")
end
if t_ then
for k, v in pairs( t_) do
print( "t["..tostring(k).."]", v)
end
end
print()
end
local performTest = function( obj_)
-- setup the userdata with some value and a uservalue
obj_:set( 666)
-- lua 5.1->5.2 support a single table uservalue
-- lua 5.3 supports an arbitrary type uservalue
obj_:setuv( 1, makeUserValue( obj_))
-- lua 5.4 supports multiple uservalues of arbitrary types
if nupvals > 1 then
obj_:setuv( 2, "ENDUV")
end
local t =
{
["key"] = obj_,
[obj_] = "val" -- this one won't transfer because we don't support full uservalue as keys
}
-- read back the contents of the object
printDeep( "immediate:", obj_, t)
-- send the object in a linda, get it back out, read the contents
l:set( "key", obj_, t)
-- when obj_ is a deep userdata, out is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy)
-- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier
printDeep( "out of linda:", l:get( "key", 2))
-- send the object in a lane through parameter passing, the lane body returns it as return value, read the contents
local g = lanes.gen(
"package"
, {
required = { "deep_test"} -- we will transfer userdata created by this module, so we need to make this lane aware of it
}
, function( arg_, t_)
-- read contents inside lane: arg_ and t_ by argument
printDeep( "in lane, as arguments:", arg_, t_)
-- read contents inside lane: obj_ and t by upvalue
printDeep( "in lane, as upvalues:", obj_, t)
-- read contents inside lane: in linda
printDeep( "in lane, from linda:", l:get("key", 2))
return arg_, t_
end
)
h = g( obj_, t)
-- when obj_ is a deep userdata, from_lane is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy)
-- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier
printDeep( "from lane:", h[1], h[2])
end
if test_deep then
print "================================================================"
print "DEEP"
performTest( dt.new_deep(nupvals))
end
if test_clonable then
print "================================================================"
print "CLONABLE"
performTest( dt.new_clonable(nupvals))
end
|