aboutsummaryrefslogtreecommitdiff
path: root/src/deep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.cpp')
-rw-r--r--src/deep.cpp79
1 files changed, 36 insertions, 43 deletions
diff --git a/src/deep.cpp b/src/deep.cpp
index cd5a844..dd682e4 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -143,10 +143,13 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m
143 143
144void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) 144void free_deep_prelude( lua_State* L, DeepPrelude* prelude_)
145{ 145{
146 ASSERT_L(prelude_->idfunc);
147 STACK_CHECK_START_REL(L, 0);
146 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup 148 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
147 lua_pushlightuserdata( L, prelude_); 149 lua_pushlightuserdata( L, prelude_);
148 ASSERT_L( prelude_->idfunc);
149 prelude_->idfunc( L, eDO_delete); 150 prelude_->idfunc( L, eDO_delete);
151 lua_pop(L, 1);
152 STACK_CHECK(L, 0);
150} 153}
151 154
152 155
@@ -160,14 +163,10 @@ static int deep_userdata_gc( lua_State* L)
160{ 163{
161 DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1); 164 DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1);
162 DeepPrelude* p = *proxy; 165 DeepPrelude* p = *proxy;
163 Universe* U = universe_get( L);
164 int v;
165 166
166 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded 167 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
167 // in that case, we are not multithreaded and locking isn't necessary anyway 168 // in that case, we are not multithreaded and locking isn't necessary anyway
168 if( U) MUTEX_LOCK( &U->deep_lock); 169 int v{ p->m_refcount.fetch_sub(1, std::memory_order_relaxed) };
169 v = -- (p->refcount);
170 if (U) MUTEX_UNLOCK( &U->deep_lock);
171 170
172 if( v == 0) 171 if( v == 0)
173 { 172 {
@@ -202,7 +201,7 @@ static int deep_userdata_gc( lua_State* L)
202 * used in this Lua state (metatable, registring it). Otherwise, increments the 201 * used in this Lua state (metatable, registring it). Otherwise, increments the
203 * reference count. 202 * reference count.
204 */ 203 */
205char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) 204char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_)
206{ 205{
207 DeepPrelude** proxy; 206 DeepPrelude** proxy;
208 207
@@ -220,12 +219,6 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in
220 lua_pop( L, 1); // DPC 219 lua_pop( L, 1); // DPC
221 } 220 }
222 221
223 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
224 // in that case, we are not multithreaded and locking isn't necessary anyway
225 if( U) MUTEX_LOCK( &U->deep_lock);
226 ++ (prelude->refcount); // one more proxy pointing to this deep data
227 if( U) MUTEX_UNLOCK( &U->deep_lock);
228
229 STACK_GROW( L, 7); 222 STACK_GROW( L, 7);
230 STACK_CHECK_START_REL(L, 0); 223 STACK_CHECK_START_REL(L, 0);
231 224
@@ -233,6 +226,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in
233 proxy = (DeepPrelude**) lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy 226 proxy = (DeepPrelude**) lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy
234 ASSERT_L( proxy); 227 ASSERT_L( proxy);
235 *proxy = prelude; 228 *proxy = prelude;
229 prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data
236 230
237 // Get/create metatable for 'idfunc' (in this state) 231 // Get/create metatable for 'idfunc' (in this state)
238 lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy idfunc 232 lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy idfunc
@@ -378,39 +372,38 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in
378*/ 372*/
379int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) 373int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_)
380{ 374{
381 char const* errmsg;
382
383 STACK_GROW( L, 1); 375 STACK_GROW( L, 1);
384 STACK_CHECK_START_REL(L, 0); 376 STACK_CHECK_START_REL(L, 0);
377 int const oldtop{ lua_gettop(L) };
378 DeepPrelude* const prelude{ static_cast<DeepPrelude*>(idfunc(L, eDO_new)) };
379 if (prelude == nullptr)
385 { 380 {
386 int const oldtop = lua_gettop( L); 381 return luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)");
387 DeepPrelude* prelude = (DeepPrelude*) idfunc( L, eDO_new); 382 }
388 if (prelude == nullptr)
389 {
390 return luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)");
391 }
392 if( prelude->magic != DEEP_VERSION)
393 {
394 // just in case, don't leak the newly allocated deep userdata object
395 lua_pushlightuserdata( L, prelude);
396 idfunc( L, eDO_delete);
397 return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation");
398 }
399 prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1
400 prelude->idfunc = idfunc;
401 383
402 if( lua_gettop( L) - oldtop != 0) 384 if( prelude->magic != DEEP_VERSION)
403 { 385 {
404 // just in case, don't leak the newly allocated deep userdata object 386 // just in case, don't leak the newly allocated deep userdata object
405 lua_pushlightuserdata( L, prelude); 387 lua_pushlightuserdata( L, prelude);
406 idfunc( L, eDO_delete); 388 idfunc( L, eDO_delete);
407 return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); 389 return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation");
408 } 390 }
409 errmsg = push_deep_proxy( universe_get( L), L, prelude, nuv_, eLM_LaneBody); // proxy 391
410 if (errmsg != nullptr) 392 ASSERT_L(prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'push_deep_proxy' will lift it to 1
411 { 393 prelude->idfunc = idfunc;
412 return luaL_error( L, errmsg); 394
413 } 395 if( lua_gettop( L) - oldtop != 0)
396 {
397 // just in case, don't leak the newly allocated deep userdata object
398 lua_pushlightuserdata( L, prelude);
399 idfunc( L, eDO_delete);
400 return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack");
401 }
402
403 char const* const errmsg{ push_deep_proxy(L, prelude, nuv_, eLM_LaneBody) }; // proxy
404 if (errmsg != nullptr)
405 {
406 return luaL_error( L, errmsg);
414 } 407 }
415 STACK_CHECK( L, 1); 408 STACK_CHECK( L, 1);
416 return 1; 409 return 1;
@@ -471,7 +464,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L
471 lua_pop( L, 1); // ... u [uv]* 464 lua_pop( L, 1); // ... u [uv]*
472 STACK_CHECK( L, nuv); 465 STACK_CHECK( L, nuv);
473 466
474 errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u 467 errmsg = push_deep_proxy(L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u
475 468
476 // transfer all uservalues of the source in the destination 469 // transfer all uservalues of the source in the destination
477 { 470 {