X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Findirect.git;a=blobdiff_plain;f=indirect.xs;h=f020a1f52508ccdaebef759f8cfa086f160d4bbe;hp=40aebea36f97c0d56e583f19220bdf70bfc58c13;hb=0b3fd3ca50b788eb9ba7b9a1a3fbdb2266d6a40f;hpb=48aed0641a91994514808460cdc6297140a2f149 diff --git a/indirect.xs b/indirect.xs index 40aebea..f020a1f 100644 --- a/indirect.xs +++ b/indirect.xs @@ -113,12 +113,17 @@ #endif #ifndef I_MULTIPLICITY -# if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) +# if defined(MULTIPLICITY) # define I_MULTIPLICITY 1 # else # define I_MULTIPLICITY 0 # endif #endif +#if I_MULTIPLICITY +# ifndef PERL_IMPLICIT_CONTEXT +# error MULTIPLICITY builds must set PERL_IMPLICIT_CONTEXT +# endif +#endif #if I_MULTIPLICITY && !defined(tTHX) # define tTHX PerlInterpreter* #endif @@ -186,6 +191,80 @@ static void indirect_ck_restore(pTHX_ OPCODE type, indirect_ck_t *old_ck_p) { /* --- Helpers ------------------------------------------------------------- */ +/* ... Check if the module is loaded ....................................... */ + +#if I_THREADSAFE + +#define PTABLE_NAME ptable_loaded +#define PTABLE_VAL_FREE(V) NOOP + +#include "ptable.h" + +#define ptable_loaded_store(T, K, V) ptable_loaded_store(aPTBLMS_ (T), (K), (V)) +#define ptable_loaded_delete(T, K) ptable_loaded_delete(aPTBLMS_ (T), (K)) +#define ptable_loaded_free(T) ptable_loaded_free(aPTBLMS_ (T)) + +#define indirect_loaded() + +static ptable *indirect_loaded_cxts = NULL; +static U32 indirect_loaded_cxts_refcount = 0; + +/* We must use preexistent global mutexes or we will never be able to destroy + * them. */ +#if I_HAS_PERL(5, 9, 3) +# define I_LOADED_LOCK MUTEX_LOCK(&PL_my_ctx_mutex) +# define I_LOADED_UNLOCK MUTEX_UNLOCK(&PL_my_ctx_mutex) +#else +# define I_LOADED_LOCK OP_REFCNT_LOCK +# define I_LOADED_UNLOCK OP_REFCNT_UNLOCK +#endif + +static int indirect_is_loaded(pTHX_ void *cxt) { +#define indirect_is_loaded(C) indirect_is_loaded(aTHX_ (C)) + int res = 0; + + I_LOADED_LOCK; + if (indirect_loaded_cxts && ptable_fetch(indirect_loaded_cxts, cxt)) + res = 1; + I_LOADED_UNLOCK; + + return res; +} + +static void indirect_set_loaded(pTHX_ void *cxt) { +#define indirect_set_loaded(C) indirect_set_loaded(aTHX_ (C)) + I_LOADED_LOCK; + if (!indirect_loaded_cxts) { + indirect_loaded_cxts = ptable_new(); + indirect_loaded_cxts_refcount = 0; + } + ++indirect_loaded_cxts_refcount; + ptable_loaded_store(indirect_loaded_cxts, cxt, cxt); + I_LOADED_UNLOCK; +} + +static void indirect_clear_loaded(pTHX_ void *cxt) { +#define indirect_clear_loaded(C) indirect_clear_loaded(aTHX_ (C)) + I_LOADED_LOCK; + if (indirect_loaded_cxts_refcount <= 1) { + ptable_loaded_free(indirect_loaded_cxts); + indirect_loaded_cxts = NULL; + indirect_loaded_cxts_refcount = 0; + } else { + --indirect_loaded_cxts_refcount; + ptable_loaded_delete(indirect_loaded_cxts, cxt); + } + I_LOADED_UNLOCK; +} + +#else + +#define indirect_is_loaded(C) (1) +#define indirect_set_loaded(C) NOOP +#define indirect_clear_loaded(C) NOOP + +#endif + /* ... Thread-safe hints ................................................... */ #if I_WORKAROUND_REQUIRE_PROPAGATION @@ -325,10 +404,14 @@ static void indirect_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { static void indirect_thread_cleanup(pTHX_ void *ud) { dMY_CXT; + indirect_clear_loaded(&MY_CXT); + SvREFCNT_dec(MY_CXT.global_code); MY_CXT.global_code = NULL; + ptable_free(MY_CXT.map); MY_CXT.map = NULL; + ptable_hints_free(MY_CXT.tbl); MY_CXT.tbl = NULL; } @@ -468,7 +551,7 @@ static SV *indirect_detag(pTHX_ const SV *hint) { return I_HINT_CODE(h); } -static U32 indirect_hash = 0; +static VOL U32 indirect_hash = 0; static SV *indirect_hint(pTHX) { #define indirect_hint() indirect_hint(aTHX) @@ -499,11 +582,14 @@ static SV *indirect_hint(pTHX) { } #endif - if (hint && SvIOK(hint)) + if (hint && SvIOK(hint)) { return indirect_detag(hint); - else { + } else { dMY_CXT; - return MY_CXT.global_code; + if (indirect_is_loaded(&MY_CXT)) + return MY_CXT.global_code; + else + return NULL; } } @@ -559,7 +645,7 @@ static void indirect_map_delete(pTHX_ const OP *o) { #define indirect_map_delete(O) indirect_map_delete(aTHX_ (O)) dMY_CXT; - if (MY_CXT.map) + if (indirect_is_loaded(&MY_CXT) && MY_CXT.map) ptable_delete(MY_CXT.map, o); } @@ -935,7 +1021,7 @@ done: /* --- Global setup/teardown ------------------------------------------------ */ -static U32 indirect_initialized = 0; +static VOL U32 indirect_initialized = 0; static void indirect_global_teardown(pTHX_ void *root) { if (!indirect_initialized) @@ -1003,6 +1089,8 @@ static void indirect_global_setup(pTHX) { static void indirect_local_teardown(pTHX_ void *param) { dMY_CXT; + indirect_clear_loaded(&MY_CXT); + ptable_free(MY_CXT.map); MY_CXT.map = NULL; @@ -1026,6 +1114,8 @@ static void indirect_local_setup(pTHX) { MY_CXT.map = ptable_new(); MY_CXT.global_code = NULL; + indirect_set_loaded(&MY_CXT); + call_atexit(indirect_local_teardown, NULL); return; @@ -1068,6 +1158,7 @@ PPCODE: MY_CXT.tbl = t; MY_CXT.owner = aTHX; MY_CXT.global_code = global_code_dup; + indirect_set_loaded(&MY_CXT); } gv = gv_fetchpv(__PACKAGE__ "::_THREAD_CLEANUP", 0, SVt_PVCV); if (gv) {