aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deep_test/deep_test.cpp26
-rw-r--r--docs/index.html10
-rw-r--r--src/deep.cpp182
-rw-r--r--src/deep.h21
-rw-r--r--src/intercopycontext.cpp2
5 files changed, 128 insertions, 113 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp
index 9ca88df..0a09921 100644
--- a/deep_test/deep_test.cpp
+++ b/deep_test/deep_test.cpp
@@ -13,12 +13,12 @@ class MyDeepFactory : public DeepFactory
13 13
14 private: 14 private:
15 15
16 [[nodiscard]] DeepPrelude* newDeepObjectInternal(lua_State* L) const override; 16 void createMetatable(lua_State* const L_) const override
17 void deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const override;
18 void createMetatable(lua_State* L_) const override
19 { 17 {
20 luaL_getmetatable(L_, "deep"); 18 luaL_getmetatable(L_, "deep");
21 } 19 }
20 void deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* o_) const override;
21 [[nodiscard]] DeepPrelude* newDeepObjectInternal(lua_State* const L_) const override;
22 [[nodiscard]] std::string_view moduleName() const override { return std::string_view{ "deep_test" }; } 22 [[nodiscard]] std::string_view moduleName() const override { return std::string_view{ "deep_test" }; }
23}; 23};
24/*static*/ MyDeepFactory MyDeepFactory::Instance{}; 24/*static*/ MyDeepFactory MyDeepFactory::Instance{};
@@ -33,27 +33,27 @@ struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a De
33 33
34// ################################################################################################# 34// #################################################################################################
35 35
36DeepPrelude* MyDeepFactory::newDeepObjectInternal(lua_State* L) const 36DeepPrelude* MyDeepFactory::newDeepObjectInternal(lua_State* const L_) const
37{ 37{
38 MyDeepUserdata* deep_test = new MyDeepUserdata{ MyDeepFactory::Instance }; 38 MyDeepUserdata* const _deep_test{ new MyDeepUserdata{ MyDeepFactory::Instance } };
39 return deep_test; 39 return _deep_test;
40} 40}
41 41
42// ################################################################################################# 42// #################################################################################################
43 43
44void MyDeepFactory::deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const 44void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* const o_) const
45{ 45{
46 MyDeepUserdata* deep_test = static_cast<MyDeepUserdata*>(o_); 46 MyDeepUserdata* const _deep_test{ static_cast<MyDeepUserdata*>(o_) };
47 delete deep_test; 47 delete _deep_test;
48} 48}
49 49
50// ################################################################################################# 50// #################################################################################################
51 51
52[[nodiscard]] static int deep_set(lua_State* L) 52[[nodiscard]] static int deep_set(lua_State* const L_)
53{ 53{
54 MyDeepUserdata* const self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; 54 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, 1)) };
55 lua_Integer i = lua_tointeger( L, 2); 55 lua_Integer i = lua_tointeger(L_, 2);
56 self->val = i; 56 _self->val = i;
57 return 0; 57 return 0;
58} 58}
59 59
diff --git a/docs/index.html b/docs/index.html
index 8385480..19cc442 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -958,7 +958,7 @@
958 </table> 958 </table>
959 959
960<p> 960<p>
961 Only available if lane tracking feature is compiled (see <tt>HAVE_LANE_TRACKING</tt> in <tt>lanes.cpp</tt>) and <a href="#track_lanes"><tt>track_lanes</tt></a> is set. 961 Only available if lane tracking is enabled by setting <a href="#track_lanes"><tt>track_lanes</tt></a>.
962 <br/> 962 <br/>
963 Returns an array table where each entry is a table containing a lane's name and status. Returns <tt>nil</tt> if no lane is running. 963 Returns an array table where each entry is a table containing a lane's name and status. Returns <tt>nil</tt> if no lane is running.
964</p> 964</p>
@@ -1743,9 +1743,9 @@ class MyDeepFactory : public DeepFactory
1743{ 1743{
1744 private: 1744 private:
1745 1745
1746 DeepPrelude* newDeepObjectInternal(lua_State* L) const override; 1746 void createMetatable(lua_State* const L_) const override;
1747 void deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const override; 1747 void deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* o_) const override;
1748 void createMetatable(lua_State* L) const override; 1748 DeepPrelude* newDeepObjectInternal(lua_State* const L_) const override;
1749 std::string_view moduleName() const override; 1749 std::string_view moduleName() const override;
1750}; 1750};
1751 1751
@@ -1757,7 +1757,7 @@ static MyDeepFactory g_MyDeepFactory;
1757 <li><tt>createMetatable</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (<tt>createMetatable</tt> should only be invoked once per state). Just push the metatable on the stack.</li> 1757 <li><tt>createMetatable</tt>: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (<tt>createMetatable</tt> should only be invoked once per state). Just push the metatable on the stack.</li>
1758 <li><tt>moduleName</tt>: requests the name of the module that exports the factory, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the factory pointer is still held.</li> 1758 <li><tt>moduleName</tt>: requests the name of the module that exports the factory, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the factory pointer is still held.</li>
1759 </ul> 1759 </ul>
1760 Take a look at <tt>LindaFactory</tt> in <tt>linda.cpp</tt> or <tt>MyDeepFactory</tt> in <tt>deep_test.cpp</tt>. 1760 Take a look at <tt>LindaFactory</tt> in <tt>lindafactory.cpp</tt> or <tt>MyDeepFactory</tt> in <tt>deep_test.cpp</tt>.
1761 </li> 1761 </li>
1762 <li>Include <tt>"deep.h"</tt> and either link against Lanes or statically compile <tt>compat.cpp deep.cpp</tt> into your module if you want to avoid a runtime dependency for users that will use your module without Lanes. 1762 <li>Include <tt>"deep.h"</tt> and either link against Lanes or statically compile <tt>compat.cpp deep.cpp</tt> into your module if you want to avoid a runtime dependency for users that will use your module without Lanes.
1763 <li>Instanciate your userdata using <tt>yourFactoryObject.pushDeepUserdata()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given a <tt>factory</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li> 1763 <li>Instanciate your userdata using <tt>yourFactoryObject.pushDeepUserdata()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given a <tt>factory</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li>
diff --git a/src/deep.cpp b/src/deep.cpp
index dfa3579..f5716bf 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -60,51 +60,80 @@ static constexpr RegistryUniqueKey kDeepLookupRegKey{ 0xC6788345703C6059ull };
60static constexpr RegistryUniqueKey kDeepProxyCacheRegKey{ 0xEBCD49AE1A3DD35Eull }; 60static constexpr RegistryUniqueKey kDeepProxyCacheRegKey{ 0xEBCD49AE1A3DD35Eull };
61 61
62// ################################################################################################# 62// #################################################################################################
63// #################################################################################################
64namespace {
65 // #############################################################################################
66 // #############################################################################################
67
68 /*
69 * void= mt.__gc( proxy_ud )
70 *
71 * End of life for a proxy object; reduce the deep reference count and clean it up if reaches 0.
72 *
73 */
74 [[nodiscard]] static int DeepGC(lua_State* const L_)
75 {
76 DeepPrelude* const* const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, 1) };
77 DeepPrelude* const _p{ *_proxy };
78
79 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
80 // in that case, we are not multithreaded and locking isn't necessary anyway
81 bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 };
82
83 if (isLastRef) {
84 // retrieve wrapped __gc, if any
85 lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc?
86 if (!lua_isnil(L_, -1)) {
87 lua_insert(L_, -2); // L_: __gc self
88 lua_call(L_, 1, 0); // L_:
89 } else {
90 // need an empty stack in case we are GC_ing from a Keeper, so that empty stack checks aren't triggered
91 lua_pop(L_, 2); // L_:
92 }
93 DeepFactory::DeleteDeepObject(L_, _p);
94 }
95 return 0;
96 }
63 97
64/* 98 // #############################################################################################
65 * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
66 * Pops the both values off the stack.
67 */
68void DeepFactory::storeDeepLookup(lua_State* L_) const
69{
70 // the deep metatable is at the top of the stack // L_: mt
71 STACK_GROW(L_, 3);
72 STACK_CHECK_START_REL(L_, 0); // L_: mt
73 std::ignore = kDeepLookupRegKey.getSubTable(L_, 0, 0); // L_: mt {}
74 lua_pushvalue(L_, -2); // L_: mt {} mt
75 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} mt factory
76 lua_rawset(L_, -3); // L_: mt {}
77 STACK_CHECK(L_, 1);
78 99
79 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} factory 100 // Pops the key (metatable or factory) off the stack, and replaces with the deep lookup value (factory/metatable/nil).
80 lua_pushvalue(L_, -3); // L_: mt {} factory mt 101 static void LookupDeep(lua_State* const L_)
81 lua_rawset(L_, -3); // L_: mt {} 102 {
82 STACK_CHECK(L_, 1); 103 STACK_GROW(L_, 1);
104 STACK_CHECK_START_REL(L_, 1); // L_: a
105 kDeepLookupRegKey.pushValue(L_); // L_: a {}
106 if (!lua_isnil(L_, -1)) {
107 lua_insert(L_, -2); // L_: {} a
108 lua_rawget(L_, -2); // L_: {} b
109 }
110 lua_remove(L_, -2); // L_: a|b
111 STACK_CHECK(L_, 1);
112 }
83 113
84 lua_pop(L_, 1); // L_: mt 114 // #############################################################################################
85 STACK_CHECK(L_, 0); 115 // #############################################################################################
86} 116} // namespace
117// #################################################################################################
118// #################################################################################################
87 119
88// ################################################################################################# 120// #################################################################################################
121// #################################################################################################
122// ####################################### DeepFactory #############################################
123// #################################################################################################
124// #################################################################################################
89 125
90// Pops the key (metatable or factory) off the stack, and replaces with the deep lookup value (factory/metatable/nil). 126void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_)
91static void LookupDeep(lua_State* L_)
92{ 127{
93 STACK_GROW(L_, 1); 128 STACK_CHECK_START_REL(L_, 0);
94 STACK_CHECK_START_REL(L_, 1); // L_: a 129 o_->factory.deleteDeepObjectInternal(L_, o_);
95 kDeepLookupRegKey.pushValue(L_); // L_: a {} 130 STACK_CHECK(L_, 0);
96 if (!lua_isnil(L_, -1)) {
97 lua_insert(L_, -2); // L_: {} a
98 lua_rawget(L_, -2); // L_: {} b
99 }
100 lua_remove(L_, -2); // L_: a|b
101 STACK_CHECK(L_, 1);
102} 131}
103 132
104// ################################################################################################# 133// #################################################################################################
105 134
106// Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy. 135// Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy.
107[[nodiscard]] DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_) 136[[nodiscard]] DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, int const index_, LookupMode const mode_)
108{ 137{
109 // when looking inside a keeper, we are 100% sure the object is a deep userdata 138 // when looking inside a keeper, we are 100% sure the object is a deep userdata
110 if (mode_ == LookupMode::FromKeeper) { 139 if (mode_ == LookupMode::FromKeeper) {
@@ -134,47 +163,6 @@ static void LookupDeep(lua_State* L_)
134 163
135// ################################################################################################# 164// #################################################################################################
136 165
137void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_)
138{
139 STACK_CHECK_START_REL(L_, 0);
140 o_->factory.deleteDeepObjectInternal(L_, o_);
141 STACK_CHECK(L_, 0);
142}
143
144// #################################################################################################
145
146/*
147 * void= mt.__gc( proxy_ud )
148 *
149 * End of life for a proxy object; reduce the deep reference count and clean it up if reaches 0.
150 *
151 */
152[[nodiscard]] static int deep_userdata_gc(lua_State* L_)
153{
154 DeepPrelude* const* const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, 1) };
155 DeepPrelude* const _p{ *_proxy };
156
157 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
158 // in that case, we are not multithreaded and locking isn't necessary anyway
159 bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 };
160
161 if (isLastRef) {
162 // retrieve wrapped __gc, if any
163 lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc?
164 if (!lua_isnil(L_, -1)) {
165 lua_insert(L_, -2); // L_: __gc self
166 lua_call(L_, 1, 0); // L_:
167 } else {
168 // need an empty stack in case we are GC_ing from a Keeper, so that empty stack checks aren't triggered
169 lua_pop(L_, 2); // L_:
170 }
171 DeepFactory::DeleteDeepObject(L_, _p);
172 }
173 return 0;
174}
175
176// #################################################################################################
177
178/* 166/*
179 * Push a proxy userdata on the stack. 167 * Push a proxy userdata on the stack.
180 * raises an error in case of problem (error cannot happen with mode_ == LookupMode::ToKeeper) 168 * raises an error in case of problem (error cannot happen with mode_ == LookupMode::ToKeeper)
@@ -182,7 +170,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_)
182 * Initializes necessary structures if it's the first time 'factory' is being used in 170 * Initializes necessary structures if it's the first time 'factory' is being used in
183 * this Lua state (metatable, registring it). Otherwise, increments the reference count. 171 * this Lua state (metatable, registring it). Otherwise, increments the reference count.
184 */ 172 */
185void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_, lua_State* errL_) 173void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, int const nuv_, LookupMode const mode_, lua_State* const errL_)
186{ 174{
187 STACK_CHECK_START_REL(L_, 0); 175 STACK_CHECK_START_REL(L_, 0);
188 kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC 176 kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC
@@ -208,8 +196,8 @@ void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, L
208 prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data 196 prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data
209 197
210 // Get/create metatable for 'factory' (in this state) 198 // Get/create metatable for 'factory' (in this state)
211 DeepFactory& factory = prelude_->factory; 199 DeepFactory& _factory = prelude_->factory;
212 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // L_: DPC proxy factory 200 lua_pushlightuserdata(L_, std::bit_cast<void*>(&_factory)); // L_: DPC proxy _factory
213 LookupDeep(L_); // L_: DPC proxy metatable|nil 201 LookupDeep(L_); // L_: DPC proxy metatable|nil
214 202
215 if (lua_isnil(L_, -1)) { // No metatable yet. 203 if (lua_isnil(L_, -1)) { // No metatable yet.
@@ -217,7 +205,7 @@ void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, L
217 int const _oldtop{ lua_gettop(L_) }; 205 int const _oldtop{ lua_gettop(L_) };
218 // 1 - make one and register it 206 // 1 - make one and register it
219 if (mode_ != LookupMode::ToKeeper) { 207 if (mode_ != LookupMode::ToKeeper) {
220 factory.createMetatable(L_); // L_: DPC proxy metatable 208 _factory.createMetatable(L_); // L_: DPC proxy metatable
221 if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { 209 if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) {
222 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! 210 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR!
223 raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); 211 raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value");
@@ -232,18 +220,18 @@ void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, L
232 if (lua_isnil(L_, -1)) { 220 if (lua_isnil(L_, -1)) {
233 // Add our own '__gc' method 221 // Add our own '__gc' method
234 lua_pop(L_, 1); // L_: DPC proxy metatable 222 lua_pop(L_, 1); // L_: DPC proxy metatable
235 lua_pushcfunction(L_, deep_userdata_gc); // L_: DPC proxy metatable deep_userdata_gc 223 lua_pushcfunction(L_, DeepGC); // L_: DPC proxy metatable DeepGC
236 } else { 224 } else {
237 // Add our own '__gc' method wrapping the original 225 // Add our own '__gc' method wrapping the original
238 lua_pushcclosure(L_, deep_userdata_gc, 1); // L_: DPC proxy metatable deep_userdata_gc 226 lua_pushcclosure(L_, DeepGC, 1); // L_: DPC proxy metatable DeepGC
239 } 227 }
240 lua_setfield(L_, -2, "__gc"); // L_: DPC proxy metatable 228 lua_setfield(L_, -2, "__gc"); // L_: DPC proxy metatable
241 229
242 // Memorize for later rounds 230 // Memorize for later rounds
243 factory.storeDeepLookup(L_); 231 _factory.storeDeepLookup(L_);
244 232
245 // 2 - cause the target state to require the module that exported the factory 233 // 2 - cause the target state to require the module that exported the factory
246 if (std::string_view const _modname{ factory.moduleName() }; !_modname.empty()) { // we actually got a module name 234 if (std::string_view const _modname{ _factory.moduleName() }; !_modname.empty()) { // we actually got a module name
247 // L.registry._LOADED exists without having registered the 'package' library. 235 // L.registry._LOADED exists without having registered the 'package' library.
248 lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() 236 lua_getglobal(L_, "require"); // L_: DPC proxy metatable require()
249 // check that the module is already loaded (or being loaded, we are happy either way) 237 // check that the module is already loaded (or being loaded, we are happy either way)
@@ -310,7 +298,7 @@ void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, L
310 * 298 *
311 * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()' 299 * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()'
312 */ 300 */
313int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const 301int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const
314{ 302{
315 STACK_GROW(L_, 1); 303 STACK_GROW(L_, 1);
316 STACK_CHECK_START_REL(L_, 0); 304 STACK_CHECK_START_REL(L_, 0);
@@ -343,12 +331,38 @@ int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const
343// ################################################################################################# 331// #################################################################################################
344 332
345/* 333/*
334 * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
335 * Pops the both values off the stack.
336 */
337void DeepFactory::storeDeepLookup(lua_State* const L_) const
338{
339 // the deep metatable is at the top of the stack // L_: mt
340 STACK_GROW(L_, 3);
341 STACK_CHECK_START_REL(L_, 0); // L_: mt
342 std::ignore = kDeepLookupRegKey.getSubTable(L_, 0, 0); // L_: mt {}
343 lua_pushvalue(L_, -2); // L_: mt {} mt
344 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} mt factory
345 lua_rawset(L_, -3); // L_: mt {}
346 STACK_CHECK(L_, 1);
347
348 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} factory
349 lua_pushvalue(L_, -3); // L_: mt {} factory mt
350 lua_rawset(L_, -3); // L_: mt {}
351 STACK_CHECK(L_, 1);
352
353 lua_pop(L_, 1); // L_: mt
354 STACK_CHECK(L_, 0);
355}
356
357// #################################################################################################
358
359/*
346 * Access deep userdata through a proxy. 360 * Access deep userdata through a proxy.
347 * 361 *
348 * Reference count is not changed, and access to the deep userdata is not 362 * Reference count is not changed, and access to the deep userdata is not
349 * serialized. It is the module's responsibility to prevent conflicting usage. 363 * serialized. It is the module's responsibility to prevent conflicting usage.
350 */ 364 */
351DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const 365DeepPrelude* DeepFactory::toDeep(lua_State* const L_, int const index_) const
352{ 366{
353 STACK_CHECK_START_REL(L_, 0); 367 STACK_CHECK_START_REL(L_, 0);
354 // ensure it is actually a deep userdata we created 368 // ensure it is actually a deep userdata we created
diff --git a/src/deep.h b/src/deep.h
index 4b52b51..17d3491 100644
--- a/src/deep.h
+++ b/src/deep.h
@@ -63,21 +63,22 @@ class DeepFactory
63 DeepFactory& operator=(DeepFactory const&&) = delete; 63 DeepFactory& operator=(DeepFactory const&&) = delete;
64 64
65 private: 65 private:
66 void storeDeepLookup(lua_State* L_) const;
67 // NVI: private overrides 66 // NVI: private overrides
68 [[nodiscard]] virtual DeepPrelude* newDeepObjectInternal(lua_State* L_) const = 0; 67 virtual void createMetatable(lua_State* const L_) const = 0;
69 virtual void deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const = 0; 68 virtual void deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* const o_) const = 0;
70 virtual void createMetatable(lua_State* L_) const = 0; 69 [[nodiscard]] virtual DeepPrelude* newDeepObjectInternal(lua_State* const L_) const = 0;
71 [[nodiscard]] virtual std::string_view moduleName() const = 0; 70 [[nodiscard]] virtual std::string_view moduleName() const = 0;
72 71
72 private:
73 void storeDeepLookup(lua_State* const L_) const;
74
73 public: 75 public:
74 // NVI: public interface 76 // NVI: public interface
75 [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; 77 static void DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_);
76 [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; 78 [[nodiscard]] static DeepFactory* LookupFactory(lua_State* const L_, int const index_, LookupMode const mode_);
77 static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); 79 static void PushDeepProxy(DestState const L_, DeepPrelude* const o_, int const nuv_, LookupMode const mode_, lua_State* const errL_);
78 static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); 80 [[nodiscard]] int pushDeepUserdata(DestState const L_, int const nuv_) const;
81 [[nodiscard]] DeepPrelude* toDeep(lua_State* const L_, int const index_) const;
79}; 82};
80 83
81// ################################################################################################# 84// #################################################################################################
82
83[[nodiscard]] DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_);
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index 044b197..eddb309 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -723,7 +723,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const
723// Returns false if not a deep userdata, else true (unless an error occured) 723// Returns false if not a deep userdata, else true (unless an error occured)
724[[nodiscard]] bool InterCopyContext::tryCopyDeep() const 724[[nodiscard]] bool InterCopyContext::tryCopyDeep() const
725{ 725{
726 DeepFactory* const _factory{ LookupFactory(L1, L1_i, mode) }; 726 DeepFactory* const _factory{ DeepFactory::LookupFactory(L1, L1_i, mode) };
727 if (_factory == nullptr) { 727 if (_factory == nullptr) {
728 return false; // not a deep userdata 728 return false; // not a deep userdata
729 } 729 }