aboutsummaryrefslogtreecommitdiff
path: root/deep_test/deep_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deep_test/deep_test.cpp')
-rw-r--r--deep_test/deep_test.cpp340
1 files changed, 0 insertions, 340 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp
deleted file mode 100644
index cbc33ca..0000000
--- a/deep_test/deep_test.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
1#include "lanes/src/_pch.hpp"
2#include "lanes/src/deep.hpp"
3#include "lanes/src/compat.hpp"
4
5class MyDeepFactory final : public DeepFactory
6{
7 public:
8 static MyDeepFactory Instance;
9
10 private:
11 ~MyDeepFactory() override = default;
12
13 private:
14 void createMetatable(lua_State* const L_) const override
15 {
16 luaL_getmetatable(L_, "deep");
17 }
18 void deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* o_) const override;
19 [[nodiscard]]
20 DeepPrelude* newDeepObjectInternal(lua_State* const L_) const override;
21 [[nodiscard]]
22 std::string_view moduleName() const override { return std::string_view{ "deep_test" }; }
23};
24/*static*/ MyDeepFactory MyDeepFactory::Instance{};
25
26// #################################################################################################
27
28// a lanes-deep userdata. needs DeepPrelude and luaG_newdeepuserdata from Lanes code.
29struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude
30{
31 std::atomic<int> inUse{};
32 lua_Integer val{ 0 };
33 MyDeepUserdata()
34 : DeepPrelude{ MyDeepFactory::Instance }
35 {
36 }
37};
38
39// #################################################################################################
40
41DeepPrelude* MyDeepFactory::newDeepObjectInternal(lua_State* const L_) const
42{
43 MyDeepUserdata* const _deep_test{ new MyDeepUserdata };
44 return _deep_test;
45}
46
47// #################################################################################################
48
49void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* const o_) const
50{
51 MyDeepUserdata* const _deep_test{ static_cast<MyDeepUserdata*>(o_) };
52 delete _deep_test;
53}
54
55// #################################################################################################
56
57[[nodiscard]]
58static int deep_gc(lua_State* const L_)
59{
60 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
61 luaL_argcheck(L_, 1, !_self->inUse.load(), "being collected while in use!");
62 if (lua_getiuservalue(L_, kIdxTop, UserValueIndex{ 1 }) == LUA_TFUNCTION) {
63 lua_call(L_, 0, 0);
64 }
65 return 0;
66}
67
68// #################################################################################################
69
70[[nodiscard]]
71static int deep_get(lua_State* const L_)
72{
73 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
74 lua_pushinteger(L_, _self->val);
75 return 1;
76}
77
78// #################################################################################################
79
80[[nodiscard]]
81static int deep_tostring(lua_State* const L_)
82{
83 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
84 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
85 luaG_pushstring(L_, "%p:deep(%d)", _self, _self->val);
86 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
87 return 1;
88}
89
90// #################################################################################################
91
92// won't actually do anything as deep userdata don't have uservalue slots
93[[nodiscard]]
94static int deep_getuv(lua_State* L)
95{
96 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) };
97 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
98 UserValueIndex const _uv{ static_cast<UserValueIndex::type>(luaL_optinteger(L, 2, 1)) };
99 lua_getiuservalue(L, StackIndex{ 1 }, _uv);
100 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
101 return 1;
102}
103
104// #################################################################################################
105
106[[nodiscard]]
107static int deep_invoke(lua_State* L)
108{
109 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) };
110 luaL_argcheck(L, 2, lua_gettop(L) >= 2, "need something to call");
111 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
112 lua_call(L, lua_gettop(L) - 2, LUA_MULTRET);
113 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
114 return 1;
115}
116
117// #################################################################################################
118
119[[nodiscard]]
120static int deep_refcount(lua_State* const L_)
121{
122 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
123 lua_pushinteger(L_, _self->getRefcount());
124 return 1;
125}
126
127// #################################################################################################
128
129[[nodiscard]]
130static int deep_set(lua_State* const L_)
131{
132 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
133 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
134 lua_Integer _i = lua_tointeger(L_, 2);
135 _self->val = _i;
136 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
137 return 0;
138}
139
140// #################################################################################################
141
142[[nodiscard]]
143static int deep_setuv(lua_State* L)
144{
145 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) };
146 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
147 UserValueIndex const _uv{ static_cast<UserValueIndex::type>(luaL_optinteger(L, 2, 1)) };
148 lua_settop(L, 3);
149 lua_pushboolean(L, lua_setiuservalue(L, StackIndex{ 1 }, _uv) != 0);
150 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
151 return 1;
152}
153
154// #################################################################################################
155
156static luaL_Reg const deep_mt[] = {
157 { "__gc", deep_gc },
158 { "__tostring", deep_tostring },
159 { "get", deep_get },
160 { "getuv", deep_getuv },
161 { "invoke", deep_invoke },
162 { "refcount", deep_refcount },
163 { "set", deep_set },
164 { "setuv", deep_setuv },
165 { nullptr, nullptr }
166};
167
168// #################################################################################################
169
170int luaD_get_deep_count(lua_State* const L_)
171{
172 lua_pushinteger(L_, MyDeepFactory::Instance.getObjectCount());
173 return 1;
174}
175
176// #################################################################################################
177
178int luaD_new_deep(lua_State* L)
179{
180 UserValueCount const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 0)) };
181 lua_settop(L, 0);
182 MyDeepFactory::Instance.pushDeepUserdata(DestState{ L }, _nuv);
183 return 1;
184}
185
186// #################################################################################################
187// #################################################################################################
188
189struct MyClonableUserdata
190{
191 lua_Integer val;
192};
193
194// #################################################################################################
195
196[[nodiscard]]
197static int clonable_get(lua_State* const L_)
198{
199 MyClonableUserdata* const _self{ static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1)) };
200 lua_pushinteger(L_, _self->val);
201 return 1;
202}
203
204// #################################################################################################
205
206[[nodiscard]]
207static int clonable_set(lua_State* const L_)
208{
209 MyClonableUserdata* _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1));
210 lua_Integer i = lua_tointeger(L_, 2);
211 _self->val = i;
212 return 0;
213}
214
215// #################################################################################################
216
217[[nodiscard]]
218static int clonable_setuv(lua_State* const L_)
219{
220 [[maybe_unused]] MyClonableUserdata* const _self{ static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1)) };
221 UserValueIndex const _uv{ static_cast<UserValueIndex::type>(luaL_optinteger(L_, 2, 1)) };
222 lua_settop(L_, 3);
223 lua_pushboolean(L_, lua_setiuservalue(L_, StackIndex{ 1 }, _uv) != 0);
224 return 1;
225}
226
227// #################################################################################################
228
229[[nodiscard]]
230static int clonable_getuv(lua_State* const L_)
231{
232 [[maybe_unused]] MyClonableUserdata* const _self{ static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1)) };
233 UserValueIndex const _uv{ static_cast<UserValueIndex::type>(luaL_optinteger(L_, 2, 1)) };
234 lua_getiuservalue(L_, StackIndex{ 1 }, _uv);
235 return 1;
236}
237
238// #################################################################################################
239
240[[nodiscard]]
241static int clonable_tostring(lua_State* const L_)
242{
243 MyClonableUserdata* _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1));
244 luaG_pushstring(L_, "%p:clonable(%d)", lua_topointer(L_, 1), _self->val);
245 return 1;
246}
247
248// #################################################################################################
249
250[[nodiscard]]
251static int clonable_gc(lua_State* const L_)
252{
253 [[maybe_unused]] MyClonableUserdata* _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1));
254 if (lua_getiuservalue(L_, kIdxTop, UserValueIndex{ 1 }) == LUA_TFUNCTION) {
255 lua_call(L_, 0, 0);
256 }
257 return 0;
258}
259
260// #################################################################################################
261
262// this is all we need to make a userdata lanes-clonable. no dependency on Lanes code.
263[[nodiscard]]
264static int clonable_lanesclone(lua_State* L)
265{
266 switch (lua_gettop(L)) {
267 case 3:
268 {
269 MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1));
270 MyClonableUserdata* from = static_cast<MyClonableUserdata*>(lua_touserdata(L, 2));
271 size_t len = lua_tointeger(L, 3);
272 assert(len == sizeof(MyClonableUserdata));
273 *self = *from;
274 }
275 return 0;
276
277 default:
278 raise_luaL_error(L, "Lanes called clonable_lanesclone with unexpected arguments");
279 }
280 return 0;
281}
282
283// #################################################################################################
284
285static luaL_Reg const clonable_mt[] = {
286 { "__gc", clonable_gc },
287 { "__lanesclone", clonable_lanesclone },
288 { "__tostring", clonable_tostring },
289 { "get", clonable_get },
290 { "set", clonable_set },
291 { "setuv", clonable_setuv },
292 { "getuv", clonable_getuv },
293 { nullptr, nullptr }
294};
295
296// #################################################################################################
297
298int luaD_new_clonable(lua_State* L)
299{
300 UserValueCount const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) };
301 lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv);
302 luaG_setmetatable(L, "clonable");
303 return 1;
304}
305
306// #################################################################################################
307// #################################################################################################
308
309static luaL_Reg const deep_module[] = {
310 { "get_deep_count", luaD_get_deep_count },
311 { "new_deep", luaD_new_deep },
312 { "new_clonable", luaD_new_clonable },
313 { nullptr, nullptr }
314};
315
316// #################################################################################################
317
318LANES_API int luaopen_deep_test(lua_State* L)
319{
320 luaG_newlib<std::size(deep_module)>(L, deep_module); // M
321
322 // preregister the metatables for the types we can instantiate so that Lanes can know about them
323 if (luaL_newmetatable(L, "clonable")) // M mt
324 {
325 luaG_registerlibfuncs(L, clonable_mt);
326 lua_pushvalue(L, -1); // M mt mt
327 lua_setfield(L, -2, "__index"); // M mt
328 }
329 lua_setfield(L, -2, "__clonableMT"); // M
330
331 if (luaL_newmetatable(L, "deep")) // mt
332 {
333 luaG_registerlibfuncs(L, deep_mt);
334 lua_pushvalue(L, -1); // mt mt
335 lua_setfield(L, -2, "__index"); // mt
336 }
337 lua_setfield(L, -2, "__deepMT"); // M
338
339 return 1;
340}