aboutsummaryrefslogtreecommitdiff
path: root/src/deep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.c')
-rw-r--r--src/deep.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/src/deep.c b/src/deep.c
index b5d6aee..71a798c 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * DEEP.C Copyright (c) 2014, Benoit Germain 2 * DEEP.C Copyright (c) 2017, Benoit Germain
3 * 3 *
4 * Depp userdata support, separate in its own source file to help integration 4 * Deep userdata support, separate in its own source file to help integration
5 * without enforcing a Lanes dependency 5 * without enforcing a Lanes dependency
6 */ 6 */
7 7
@@ -9,7 +9,7 @@
9=============================================================================== 9===============================================================================
10 10
11Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> 11Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com>
12 2011-14 Benoit Germain <bnt.germain@gmail.com> 12 2011-17 Benoit Germain <bnt.germain@gmail.com>
13 13
14Permission is hereby granted, free of charge, to any person obtaining a copy 14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal 15of this software and associated documentation files (the "Software"), to deal
@@ -34,6 +34,7 @@ THE SOFTWARE.
34 34
35#include "compat.h" 35#include "compat.h"
36#include "tools.h" 36#include "tools.h"
37#include "universe.h"
37#include "deep.h" 38#include "deep.h"
38 39
39#include <stdio.h> 40#include <stdio.h>
@@ -120,14 +121,15 @@ void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "f248e77a-
120* metatable -> idfunc 121* metatable -> idfunc
121* idfunc -> metatable 122* idfunc -> metatable
122*/ 123*/
123#define DEEP_LOOKUP_KEY ((void*)set_deep_lookup) 124// crc64/we of string "DEEP_LOOKUP_KEY" generated at https://www.nitrxgen.net/hashgen/
124 // any unique light userdata 125#define DEEP_LOOKUP_KEY ((void*)0x9fb9b4f3f633d83d)
125 126
126 127
127/* 128/*
128* The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying 129 * The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying
130 * crc64/we of string "DEEP_PROXY_CACHE_KEY" generated at https://www.nitrxgen.net/hashgen/
129*/ 131*/
130#define DEEP_PROXY_CACHE_KEY ((void*)push_deep_proxy) 132#define DEEP_PROXY_CACHE_KEY ((void*)0x05773d6fc26be106)
131 133
132/* 134/*
133* Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. 135* Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
@@ -163,7 +165,7 @@ static void get_deep_lookup( lua_State* L)
163 { 165 {
164 lua_insert( L, -2); // {} a 166 lua_insert( L, -2); // {} a
165 lua_rawget( L, -2); // {} b 167 lua_rawget( L, -2); // {} b
166 } 168 }
167 lua_remove( L, -2); // a|b 169 lua_remove( L, -2); // a|b
168 STACK_END( L, 0); 170 STACK_END( L, 0);
169} 171}
@@ -177,7 +179,7 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupM
177 // when looking inside a keeper, we are 100% sure the object is a deep userdata 179 // when looking inside a keeper, we are 100% sure the object is a deep userdata
178 if( mode_ == eLM_FromKeeper) 180 if( mode_ == eLM_FromKeeper)
179 { 181 {
180 DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, index); 182 struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, index);
181 // we can (and must) cast and fetch the internally stored idfunc 183 // we can (and must) cast and fetch the internally stored idfunc
182 return (*proxy)->idfunc; 184 return (*proxy)->idfunc;
183 } 185 }
@@ -206,7 +208,7 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupM
206} 208}
207 209
208 210
209void free_deep_prelude( lua_State* L, DEEP_PRELUDE* prelude_) 211void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_)
210{ 212{
211 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup 213 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
212 lua_pushlightuserdata( L, prelude_->deep); 214 lua_pushlightuserdata( L, prelude_->deep);
@@ -224,16 +226,18 @@ void free_deep_prelude( lua_State* L, DEEP_PRELUDE* prelude_)
224*/ 226*/
225static int deep_userdata_gc( lua_State* L) 227static int deep_userdata_gc( lua_State* L)
226{ 228{
227 DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, 1); 229 struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, 1);
228 DEEP_PRELUDE* p = *proxy; 230 struct DEEP_PRELUDE* p = *proxy;
229 struct s_Universe* U = get_universe( L); 231 struct s_Universe* U = universe_get( L);
230 int v; 232 int v;
231 233
232 *proxy = 0; // make sure we don't use it any more 234 *proxy = 0; // make sure we don't use it any more
233 235
234 MUTEX_LOCK( &U->deep_lock); 236 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
237 // in that case, we are not multithreaded and locking isn't necessary anyway
238 if( U) MUTEX_LOCK( &U->deep_lock);
235 v = -- (p->refcount); 239 v = -- (p->refcount);
236 MUTEX_UNLOCK( &U->deep_lock); 240 if (U) MUTEX_UNLOCK( &U->deep_lock);
237 241
238 if( v == 0) 242 if( v == 0)
239 { 243 {
@@ -260,9 +264,9 @@ static int deep_userdata_gc( lua_State* L)
260 * used in this Lua state (metatable, registring it). Otherwise, increments the 264 * used in this Lua state (metatable, registring it). Otherwise, increments the
261 * reference count. 265 * reference count.
262 */ 266 */
263char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_) 267char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRELUDE* prelude, enum eLookupMode mode_)
264{ 268{
265 DEEP_PRELUDE** proxy; 269 struct DEEP_PRELUDE** proxy;
266 270
267 // Check if a proxy already exists 271 // Check if a proxy already exists
268 push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC 272 push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC
@@ -278,14 +282,16 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* p
278 lua_pop( L, 1); // DPC 282 lua_pop( L, 1); // DPC
279 } 283 }
280 284
281 MUTEX_LOCK( &U->deep_lock); 285 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
286 // in that case, we are not multithreaded and locking isn't necessary anyway
287 if( U) MUTEX_LOCK( &U->deep_lock);
282 ++ (prelude->refcount); // one more proxy pointing to this deep data 288 ++ (prelude->refcount); // one more proxy pointing to this deep data
283 MUTEX_UNLOCK( &U->deep_lock); 289 if( U) MUTEX_UNLOCK( &U->deep_lock);
284 290
285 STACK_GROW( L, 7); 291 STACK_GROW( L, 7);
286 STACK_CHECK( L); 292 STACK_CHECK( L);
287 293
288 proxy = lua_newuserdata( L, sizeof( DEEP_PRELUDE*)); // DPC proxy 294 proxy = lua_newuserdata( L, sizeof(struct DEEP_PRELUDE*)); // DPC proxy
289 ASSERT_L( proxy); 295 ASSERT_L( proxy);
290 *proxy = prelude; 296 *proxy = prelude;
291 297
@@ -301,7 +307,7 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* p
301 // 1 - make one and register it 307 // 1 - make one and register it
302 if( mode_ != eLM_ToKeeper) 308 if( mode_ != eLM_ToKeeper)
303 { 309 {
304 prelude->idfunc( L, eDO_metatable); // DPC proxy metatable deepversion 310 (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable deepversion
305 if( lua_gettop( L) - oldtop != 1 || !lua_istable( L, -2) || !lua_isstring( L, -1)) 311 if( lua_gettop( L) - oldtop != 1 || !lua_istable( L, -2) || !lua_isstring( L, -1))
306 { 312 {
307 lua_settop( L, oldtop); // DPC proxy X 313 lua_settop( L, oldtop); // DPC proxy X
@@ -350,7 +356,7 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* p
350 return "Bad idfunc(eOP_module): should not push anything"; 356 return "Bad idfunc(eOP_module): should not push anything";
351 } 357 }
352 } 358 }
353 if( modname) // we actually got a module name 359 if( NULL != modname) // we actually got a module name
354 { 360 {
355 // somehow, L.registry._LOADED can exist without having registered the 'package' library. 361 // somehow, L.registry._LOADED can exist without having registered the 'package' library.
356 lua_getglobal( L, "require"); // DPC proxy metatable require() 362 lua_getglobal( L, "require"); // DPC proxy metatable require()
@@ -413,7 +419,6 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* p
413 return NULL; 419 return NULL;
414} 420}
415 421
416
417/* 422/*
418* Create a deep userdata 423* Create a deep userdata
419* 424*
@@ -439,7 +444,7 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* p
439int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) 444int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc)
440{ 445{
441 char const* errmsg; 446 char const* errmsg;
442 DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(DEEP_PRELUDE)); 447 struct DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(struct DEEP_PRELUDE));
443 if( prelude == NULL) 448 if( prelude == NULL)
444 { 449 {
445 return luaL_error( L, "couldn't not allocate deep prelude: out of memory"); 450 return luaL_error( L, "couldn't not allocate deep prelude: out of memory");
@@ -463,7 +468,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc)
463 luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); 468 luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack");
464 } 469 }
465 } 470 }
466 errmsg = push_deep_proxy( get_universe( L), L, prelude, eLM_LaneBody); // proxy 471 errmsg = push_deep_proxy( universe_get( L), L, prelude, eLM_LaneBody); // proxy
467 if( errmsg != NULL) 472 if( errmsg != NULL)
468 { 473 {
469 luaL_error( L, errmsg); 474 luaL_error( L, errmsg);
@@ -481,7 +486,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc)
481*/ 486*/
482void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) 487void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index)
483{ 488{
484 DEEP_PRELUDE** proxy; 489 struct DEEP_PRELUDE** proxy;
485 490
486 STACK_CHECK( L); 491 STACK_CHECK( L);
487 // ensure it is actually a deep userdata 492 // ensure it is actually a deep userdata
@@ -490,7 +495,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index)
490 return NULL; // no metatable, or wrong kind 495 return NULL; // no metatable, or wrong kind
491 } 496 }
492 497
493 proxy = (DEEP_PRELUDE**) lua_touserdata( L, index); 498 proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, index);
494 STACK_END( L, 0); 499 STACK_END( L, 0);
495 500
496 return (*proxy)->deep; 501 return (*proxy)->deep;
@@ -513,7 +518,7 @@ luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int
513 return NULL; // not a deep userdata 518 return NULL; // not a deep userdata
514 } 519 }
515 520
516 errmsg = push_deep_proxy( U, L2, *(DEEP_PRELUDE**) lua_touserdata( L, index), mode_); 521 errmsg = push_deep_proxy( U, L2, *(struct DEEP_PRELUDE**) lua_touserdata( L, index), mode_);
517 if( errmsg != NULL) 522 if( errmsg != NULL)
518 { 523 {
519 // raise the error in the proper state (not the keeper) 524 // raise the error in the proper state (not the keeper)