aboutsummaryrefslogtreecommitdiff
path: root/src/deep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.cpp')
-rw-r--r--src/deep.cpp176
1 files changed, 88 insertions, 88 deletions
diff --git a/src/deep.cpp b/src/deep.cpp
index af7e814..13932a4 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -107,12 +107,12 @@ static void get_deep_lookup(lua_State* L_)
107* Return the registered factory for 'index' (deep userdata proxy), 107* Return the registered factory for 'index' (deep userdata proxy),
108* or nullptr if 'index' is not a deep userdata proxy. 108* or nullptr if 'index' is not a deep userdata proxy.
109*/ 109*/
110[[nodiscard]] static inline DeepFactory* get_factory(lua_State* L_, int index, LookupMode mode_) 110[[nodiscard]] static inline DeepFactory* get_factory(lua_State* L_, int index_, LookupMode mode_)
111{ 111{
112 // when looking inside a keeper, we are 100% sure the object is a deep userdata 112 // when looking inside a keeper, we are 100% sure the object is a deep userdata
113 if (mode_ == LookupMode::FromKeeper) 113 if (mode_ == LookupMode::FromKeeper)
114 { 114 {
115 DeepPrelude* const proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index) }; 115 DeepPrelude* const proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index_) };
116 // we can (and must) cast and fetch the internally stored factory 116 // we can (and must) cast and fetch the internally stored factory
117 return &proxy->m_factory; 117 return &proxy->m_factory;
118 } 118 }
@@ -124,7 +124,7 @@ static void get_deep_lookup(lua_State* L_)
124 STACK_GROW( L_, 1); 124 STACK_GROW( L_, 1);
125 STACK_CHECK_START_REL(L_, 0); 125 STACK_CHECK_START_REL(L_, 0);
126 126
127 if (!lua_getmetatable( L_, index)) // deep ... metatable? 127 if (!lua_getmetatable( L_, index_)) // deep ... metatable?
128 { 128 {
129 return nullptr; // no metatable: can't be a deep userdata object! 129 return nullptr; // no metatable: can't be a deep userdata object!
130 } 130 }
@@ -168,11 +168,11 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_)
168 if (isLastRef) 168 if (isLastRef)
169 { 169 {
170 // retrieve wrapped __gc 170 // retrieve wrapped __gc
171 lua_pushvalue( L_, lua_upvalueindex( 1)); // self __gc? 171 lua_pushvalue(L_, lua_upvalueindex( 1)); // self __gc?
172 if (!lua_isnil( L_, -1)) 172 if (!lua_isnil(L_, -1))
173 { 173 {
174 lua_insert( L_, -2); // __gc self 174 lua_insert(L_, -2); // __gc self
175 lua_call( L_, 1, 0); // 175 lua_call(L_, 1, 0); //
176 } 176 }
177 else 177 else
178 { 178 {
@@ -195,138 +195,138 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_)
195 * used in this Lua state (metatable, registring it). Otherwise, increments the 195 * used in this Lua state (metatable, registring it). Otherwise, increments the
196 * reference count. 196 * reference count.
197 */ 197 */
198char const* DeepFactory::PushDeepProxy(DestState L, DeepPrelude* prelude, int nuv_, LookupMode mode_) 198char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_)
199{ 199{
200 // Check if a proxy already exists 200 // Check if a proxy already exists
201 push_registry_subtable_mode(L, kDeepProxyCacheRegKey, "v"); // DPC 201 push_registry_subtable_mode(L_, kDeepProxyCacheRegKey, "v"); // DPC
202 lua_pushlightuserdata(L, prelude); // DPC deep 202 lua_pushlightuserdata(L_, prelude_); // DPC deep
203 lua_rawget(L, -2); // DPC proxy 203 lua_rawget(L_, -2); // DPC proxy
204 if (!lua_isnil(L, -1)) 204 if (!lua_isnil(L_, -1))
205 { 205 {
206 lua_remove(L, -2); // proxy 206 lua_remove(L_, -2); // proxy
207 return nullptr; 207 return nullptr;
208 } 208 }
209 else 209 else
210 { 210 {
211 lua_pop(L, 1); // DPC 211 lua_pop(L_, 1); // DPC
212 } 212 }
213 213
214 STACK_GROW(L, 7); 214 STACK_GROW(L_, 7);
215 STACK_CHECK_START_REL(L, 0); 215 STACK_CHECK_START_REL(L_, 0);
216 216
217 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) 217 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4)
218 DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L, nuv_) }; // DPC proxy 218 DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // DPC proxy
219 LUA_ASSERT(L, proxy); 219 LUA_ASSERT(L_, proxy);
220 *proxy = prelude; 220 *proxy = prelude_;
221 prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data 221 prelude_->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data
222 222
223 // Get/create metatable for 'factory' (in this state) 223 // Get/create metatable for 'factory' (in this state)
224 DeepFactory& factory = prelude->m_factory; 224 DeepFactory& factory = prelude_->m_factory;
225 lua_pushlightuserdata( L, std::bit_cast<void*>(&factory)); // DPC proxy factory 225 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // DPC proxy factory
226 get_deep_lookup( L); // DPC proxy metatable? 226 get_deep_lookup(L_); // DPC proxy metatable?
227 227
228 if (lua_isnil( L, -1)) // // No metatable yet. 228 if (lua_isnil(L_, -1)) // // No metatable yet.
229 { 229 {
230 lua_pop(L, 1); // DPC proxy 230 lua_pop(L_, 1); // DPC proxy
231 int const oldtop{ lua_gettop(L) }; 231 int const oldtop{ lua_gettop(L_) };
232 // 1 - make one and register it 232 // 1 - make one and register it
233 if (mode_ != LookupMode::ToKeeper) 233 if (mode_ != LookupMode::ToKeeper)
234 { 234 {
235 factory.createMetatable(L); // DPC proxy metatable 235 factory.createMetatable(L_); // DPC proxy metatable
236 if (lua_gettop(L) - oldtop != 1 || !lua_istable(L, -1)) 236 if (lua_gettop(L_) - oldtop != 1 || !lua_istable(L_, -1))
237 { 237 {
238 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! 238 // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR!
239 lua_settop( L, oldtop); // DPC proxy X 239 lua_settop(L_, oldtop); // DPC proxy X
240 lua_pop( L, 3); // 240 lua_pop(L_, 3); //
241 return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; 241 return "Bad DeepFactory::createMetatable overload: unexpected pushed value";
242 } 242 }
243 // if the metatable contains a __gc, we will call it from our own 243 // if the metatable contains a __gc, we will call it from our own
244 lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc 244 lua_getfield(L_, -1, "__gc"); // DPC proxy metatable __gc
245 } 245 }
246 else 246 else
247 { 247 {
248 // keepers need a minimal metatable that only contains our own __gc 248 // keepers need a minimal metatable that only contains our own __gc
249 lua_newtable( L); // DPC proxy metatable 249 lua_newtable(L_); // DPC proxy metatable
250 lua_pushnil( L); // DPC proxy metatable nil 250 lua_pushnil(L_); // DPC proxy metatable nil
251 } 251 }
252 if (lua_isnil( L, -1)) 252 if (lua_isnil(L_, -1))
253 { 253 {
254 // Add our own '__gc' method 254 // Add our own '__gc' method
255 lua_pop( L, 1); // DPC proxy metatable 255 lua_pop(L_, 1); // DPC proxy metatable
256 lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc 256 lua_pushcfunction(L_, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc
257 } 257 }
258 else 258 else
259 { 259 {
260 // Add our own '__gc' method wrapping the original 260 // Add our own '__gc' method wrapping the original
261 lua_pushcclosure( L, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc 261 lua_pushcclosure(L_, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc
262 } 262 }
263 lua_setfield( L, -2, "__gc"); // DPC proxy metatable 263 lua_setfield(L_, -2, "__gc"); // DPC proxy metatable
264 264
265 // Memorize for later rounds 265 // Memorize for later rounds
266 lua_pushvalue( L, -1); // DPC proxy metatable metatable 266 lua_pushvalue(L_, -1); // DPC proxy metatable metatable
267 lua_pushlightuserdata(L, std::bit_cast<void*>(&factory)); // DPC proxy metatable metatable factory 267 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // DPC proxy metatable metatable factory
268 set_deep_lookup( L); // DPC proxy metatable 268 set_deep_lookup(L_); // DPC proxy metatable
269 269
270 // 2 - cause the target state to require the module that exported the factory 270 // 2 - cause the target state to require the module that exported the factory
271 if (char const* const modname{ factory.moduleName() }; modname) // we actually got a module name 271 if (char const* const modname{ factory.moduleName() }; modname) // we actually got a module name
272 { 272 {
273 // L.registry._LOADED exists without having registered the 'package' library. 273 // L.registry._LOADED exists without having registered the 'package' library.
274 lua_getglobal( L, "require"); // DPC proxy metatable require() 274 lua_getglobal(L_, "require"); // DPC proxy metatable require()
275 // check that the module is already loaded (or being loaded, we are happy either way) 275 // check that the module is already loaded (or being loaded, we are happy either way)
276 if (lua_isfunction( L, -1)) 276 if (lua_isfunction(L_, -1))
277 { 277 {
278 lua_pushstring( L, modname); // DPC proxy metatable require() "module" 278 lua_pushstring(L_, modname); // DPC proxy metatable require() "module"
279 lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED 279 lua_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED
280 if (lua_istable( L, -1)) 280 if (lua_istable(L_, -1))
281 { 281 {
282 lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" 282 lua_pushvalue(L_, -2); // DPC proxy metatable require() "module" _R._LOADED "module"
283 lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module 283 lua_rawget(L_, -2); // DPC proxy metatable require() "module" _R._LOADED module
284 int const alreadyloaded = lua_toboolean( L, -1); 284 int const alreadyloaded = lua_toboolean(L_, -1);
285 if (!alreadyloaded) // not loaded 285 if (!alreadyloaded) // not loaded
286 { 286 {
287 int require_result; 287 int require_result;
288 lua_pop( L, 2); // DPC proxy metatable require() "module" 288 lua_pop(L_, 2); // DPC proxy metatable require() "module"
289 // require "modname" 289 // require "modname"
290 require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? 290 require_result = lua_pcall(L_, 1, 0, 0); // DPC proxy metatable error?
291 if (require_result != LUA_OK) 291 if (require_result != LUA_OK)
292 { 292 {
293 // failed, return the error message 293 // failed, return the error message
294 lua_pushfstring( L, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); 294 lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname);
295 lua_insert( L, -2); // DPC proxy metatable prefix error 295 lua_insert(L_, -2); // DPC proxy metatable prefix error
296 lua_concat( L, 2); // DPC proxy metatable error 296 lua_concat(L_, 2); // DPC proxy metatable error
297 return lua_tostring( L, -1); 297 return lua_tostring(L_, -1);
298 } 298 }
299 } 299 }
300 else // already loaded, we are happy 300 else // already loaded, we are happy
301 { 301 {
302 lua_pop( L, 4); // DPC proxy metatable 302 lua_pop(L_, 4); // DPC proxy metatable
303 } 303 }
304 } 304 }
305 else // no L.registry._LOADED; can this ever happen? 305 else // no L.registry._LOADED; can this ever happen?
306 { 306 {
307 lua_pop( L, 6); // 307 lua_pop(L_, 6); //
308 return "unexpected error while requiring a module identified by DeepFactory::moduleName"; 308 return "unexpected error while requiring a module identified by DeepFactory::moduleName";
309 } 309 }
310 } 310 }
311 else // a module name, but no require() function :-( 311 else // a module name, but no require() function :-(
312 { 312 {
313 lua_pop( L, 4); // 313 lua_pop(L_, 4); //
314 return "lanes receiving deep userdata should register the 'package' library"; 314 return "lanes receiving deep userdata should register the 'package' library";
315 } 315 }
316 } 316 }
317 } 317 }
318 STACK_CHECK(L, 2); // DPC proxy metatable 318 STACK_CHECK(L_, 2); // DPC proxy metatable
319 LUA_ASSERT(L, lua_type_as_enum(L, -2) == LuaType::USERDATA); 319 LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA);
320 LUA_ASSERT(L, lua_istable( L, -1)); 320 LUA_ASSERT(L_, lua_istable(L_, -1));
321 lua_setmetatable( L, -2); // DPC proxy 321 lua_setmetatable(L_, -2); // DPC proxy
322 322
323 // If we're here, we obviously had to create a new proxy, so cache it. 323 // If we're here, we obviously had to create a new proxy, so cache it.
324 lua_pushlightuserdata( L, prelude); // DPC proxy deep 324 lua_pushlightuserdata(L_, prelude_); // DPC proxy deep
325 lua_pushvalue( L, -2); // DPC proxy deep proxy 325 lua_pushvalue(L_, -2); // DPC proxy deep proxy
326 lua_rawset( L, -4); // DPC proxy 326 lua_rawset(L_, -4); // DPC proxy
327 lua_remove( L, -2); // proxy 327 lua_remove(L_, -2); // proxy
328 LUA_ASSERT(L, lua_type_as_enum(L, -1) == LuaType::USERDATA); 328 LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA);
329 STACK_CHECK(L, 0); 329 STACK_CHECK(L_, 0);
330 return nullptr; 330 return nullptr;
331} 331}
332 332
@@ -347,40 +347,40 @@ char const* DeepFactory::PushDeepProxy(DestState L, DeepPrelude* prelude, int nu
347* 347*
348* Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()' 348* Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()'
349*/ 349*/
350int DeepFactory::pushDeepUserdata(DestState L, int nuv_) const 350int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const
351{ 351{
352 STACK_GROW( L, 1); 352 STACK_GROW(L_, 1);
353 STACK_CHECK_START_REL(L, 0); 353 STACK_CHECK_START_REL(L_, 0);
354 int const oldtop{ lua_gettop(L) }; 354 int const oldtop{ lua_gettop(L_) };
355 DeepPrelude* const prelude{ newDeepObjectInternal(L) }; 355 DeepPrelude* const prelude{ newDeepObjectInternal(L_) };
356 if (prelude == nullptr) 356 if (prelude == nullptr)
357 { 357 {
358 raise_luaL_error(L, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); 358 raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)");
359 } 359 }
360 360
361 if (prelude->m_magic != kDeepVersion) 361 if (prelude->m_magic != kDeepVersion)
362 { 362 {
363 // just in case, don't leak the newly allocated deep userdata object 363 // just in case, don't leak the newly allocated deep userdata object
364 deleteDeepObjectInternal(L, prelude); 364 deleteDeepObjectInternal(L_, prelude);
365 raise_luaL_error(L, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); 365 raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation");
366 } 366 }
367 367
368 LUA_ASSERT(L, prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 368 LUA_ASSERT(L_, prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1
369 LUA_ASSERT(L, &prelude->m_factory == this); 369 LUA_ASSERT(L_, &prelude->m_factory == this);
370 370
371 if (lua_gettop( L) - oldtop != 0) 371 if (lua_gettop(L_) - oldtop != 0)
372 { 372 {
373 // just in case, don't leak the newly allocated deep userdata object 373 // just in case, don't leak the newly allocated deep userdata object
374 deleteDeepObjectInternal(L, prelude); 374 deleteDeepObjectInternal(L_, prelude);
375 raise_luaL_error(L, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); 375 raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack");
376 } 376 }
377 377
378 char const* const errmsg{ DeepFactory::PushDeepProxy(L, prelude, nuv_, LookupMode::LaneBody) }; // proxy 378 char const* const errmsg{ DeepFactory::PushDeepProxy(L_, prelude, nuv_, LookupMode::LaneBody) }; // proxy
379 if (errmsg != nullptr) 379 if (errmsg != nullptr)
380 { 380 {
381 raise_luaL_error(L, errmsg); 381 raise_luaL_error(L_, errmsg);
382 } 382 }
383 STACK_CHECK( L, 1); 383 STACK_CHECK(L_, 1);
384 return 1; 384 return 1;
385} 385}
386 386
@@ -392,24 +392,24 @@ int DeepFactory::pushDeepUserdata(DestState L, int nuv_) const
392* Reference count is not changed, and access to the deep userdata is not 392* Reference count is not changed, and access to the deep userdata is not
393* serialized. It is the module's responsibility to prevent conflicting usage. 393* serialized. It is the module's responsibility to prevent conflicting usage.
394*/ 394*/
395DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index) const 395DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const
396{ 396{
397 STACK_CHECK_START_REL(L_, 0); 397 STACK_CHECK_START_REL(L_, 0);
398 // ensure it is actually a deep userdata we created 398 // ensure it is actually a deep userdata we created
399 if (get_factory(L_, index, LookupMode::LaneBody) != this) 399 if (get_factory(L_, index_, LookupMode::LaneBody) != this)
400 { 400 {
401 return nullptr; // no metatable, or wrong kind 401 return nullptr; // no metatable, or wrong kind
402 } 402 }
403 STACK_CHECK(L_, 0); 403 STACK_CHECK(L_, 0);
404 404
405 DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index) }; 405 DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) };
406 return *proxy; 406 return *proxy;
407} 407}
408 408
409// ################################################################################################# 409// #################################################################################################
410 410
411/* 411/*
412 * Copy deep userdata between two separate Lua states (from L to L2) 412 * Copy deep userdata between two separate Lua states (from L1 to L2)
413 * 413 *
414 * Returns: 414 * Returns:
415 * the id function of the copied value, or nullptr for non-deep userdata 415 * the id function of the copied value, or nullptr for non-deep userdata