]> git.vpit.fr Git - perl/modules/Variable-Magic.git/blobdiff - Magic.xs
Share the vtables with threaded perls
[perl/modules/Variable-Magic.git] / Magic.xs
index f8a465037948eafdf03535aa19f232a06c9ee786..3fb9739614332542a19485443cc7d737c4a6fa50 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
 # define MY_CXT_CLONE NOOP
 #endif
 
+#if VMG_THREADSAFE
+# define VMG_LOCK(M)   MUTEX_LOCK(M)
+# define VMG_UNLOCK(M) MUTEX_UNLOCK(M)
+#else
+# define VMG_LOCK(M)
+# define VMG_UNLOCK(M)
+#endif
+
 #if VMG_THREADSAFE
 
 STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) {
@@ -124,7 +132,7 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) {
 #endif
 
 #ifndef SvREFCNT_inc_simple_void
-# define SvREFCNT_inc_simple_void(sv) SvREFCNT_inc(sv)
+# define SvREFCNT_inc_simple_void(sv) ((void) SvREFCNT_inc(sv))
 #endif
 
 #ifndef mPUSHu
@@ -139,14 +147,6 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) {
 # define PERL_MAGIC_tied 'P'
 #endif
 
-#ifndef MGf_COPY
-# define MGf_COPY 0
-#endif
-
-#ifndef MGf_DUP
-# define MGf_DUP 0
-#endif
-
 #ifndef MGf_LOCAL
 # define MGf_LOCAL 0
 #endif
@@ -431,22 +431,87 @@ STATIC const char vmg_argstorefailed[] = "Error while storing arguments";
 #define SIG_WZO ((U16) (0x3891))
 #define SIG_WIZ ((U16) (0x3892))
 
-/* --- MGWIZ structure ----------------------------------------------------- */
+/* --- <vmg_vtable> structure ---------------------------------------------- */
+
+#if VMG_THREADSAFE
 
 typedef struct {
  MGVTBL *vtbl;
+ U32     refcount;
+} vmg_vtable;
+
+STATIC vmg_vtable *vmg_vtable_alloc(pTHX) {
+#define vmg_vtable_alloc() vmg_vtable_alloc(aTHX)
+ vmg_vtable *t;
+
+ t = VOID2(vmg_vtable *, PerlMemShared_malloc(sizeof *t));
+
+ t->vtbl     = VOID2(MGVTBL *, PerlMemShared_malloc(sizeof *t->vtbl));
+ t->refcount = 1;
+
+ return t;
+}
+
+#define vmg_vtable_vtbl(T) (T)->vtbl
+
+#if VMG_THREADSAFE
+STATIC perl_mutex vmg_vtable_refcount_mutex;
+#endif
+
+STATIC vmg_vtable *vmg_vtable_dup(pTHX_ vmg_vtable *t) {
+#define vmg_vtable_dup(T) vmg_vtable_dup(aTHX_ (T))
+ VMG_LOCK(&vmg_vtable_refcount_mutex);
+ ++t->refcount;
+ VMG_UNLOCK(&vmg_vtable_refcount_mutex);
+
+ return t;
+}
+
+STATIC void vmg_vtable_free(pTHX_ vmg_vtable *t) {
+#define vmg_vtable_free(T) vmg_vtable_free(aTHX_ (T))
+ U32 refcount;
+
+ VMG_LOCK(&vmg_vtable_refcount_mutex);
+ refcount = --t->refcount;
+ VMG_UNLOCK(&vmg_vtable_refcount_mutex);
+
+ if (!refcount) {
+  PerlMemShared_free(t->vtbl);
+  PerlMemShared_free(t);
+ }
+}
+
+#else /* VMG_THREADSAFE */
+
+typedef MGVTBL vmg_vtable;
+
+STATIC vmg_vtable *vmg_vtable_alloc(pTHX) {
+#define vmg_vtable_alloc() vmg_vtable_alloc(aTHX)
+ vmg_vtable *t;
+
+ Newx(t, 1, vmg_vtable);
+
+ return t;
+}
+
+#define vmg_vtable_vtbl(T) ((MGVTBL *) (T))
+
+#define vmg_vtable_free(T) Safefree(T)
+
+#endif /* !VMG_THREADSAFE */
+
+/* --- MGWIZ structure ----------------------------------------------------- */
+
+typedef struct {
+ vmg_vtable *vtable;
 
  U8 opinfo;
  U8 uvar;
 
  SV *cb_data;
  SV *cb_get, *cb_set, *cb_len, *cb_clear, *cb_free;
-#if MGf_COPY
  SV *cb_copy;
-#endif /* MGf_COPY */
-#if MGf_DUP
  SV *cb_dup;
-#endif /* MGf_DUP */
 #if MGf_LOCAL
  SV *cb_local;
 #endif /* MGf_LOCAL */
@@ -459,6 +524,25 @@ typedef struct {
 #endif /* VMG_MULTIPLICITY */
 } MGWIZ;
 
+STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo);
+
+STATIC MGWIZ *vmg_mgwiz_alloc(pTHX_ UV opinfo) {
+#define vmg_mgwiz_alloc(O) vmg_mgwiz_alloc(aTHX_ (O))
+ MGWIZ  *w;
+ MGVTBL *t;
+
+ Newx(w, 1, MGWIZ);
+
+ w->uvar   = 0;
+ w->opinfo = (U8) ((opinfo < 255) ? opinfo : 255);
+ if (w->opinfo)
+  vmg_op_info_init(aTHX_ w->opinfo);
+
+ w->vtable = vmg_vtable_alloc();
+
+ return w;
+}
+
 STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) {
 #define vmg_mgwiz_free(W) vmg_mgwiz_free(aTHX_ (W))
  if (!w)
@@ -479,12 +563,10 @@ STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) {
  SvREFCNT_dec(w->cb_len);
  SvREFCNT_dec(w->cb_clear);
  SvREFCNT_dec(w->cb_free);
-#if MGf_COPY
  SvREFCNT_dec(w->cb_copy);
-#endif /* MGf_COPY */
-#if 0 /* MGf_DUP */
+#if 0
  SvREFCNT_dec(w->cb_dup);
-#endif /* MGf_DUP */
+#endif
 #if MGf_LOCAL
  SvREFCNT_dec(w->cb_local);
 #endif /* MGf_LOCAL */
@@ -495,7 +577,7 @@ STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) {
  SvREFCNT_dec(w->cb_delete);
 #endif /* VMG_UVAR */
 
Safefree(w->vtbl);
vmg_vtable_free(w->vtable);
  Safefree(w);
 
  return;
@@ -509,18 +591,14 @@ STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) {
 
 STATIC MGWIZ *vmg_mgwiz_clone(pTHX_ const MGWIZ *w) {
 #define vmg_mgwiz_clone(W) vmg_mgwiz_clone(aTHX_ (W))
- MGVTBL *t;
  MGWIZ *z;
 
  if (!w)
   return NULL;
 
- Newx(t, 1, MGVTBL);
- Copy(w->vtbl, t, 1, MGVTBL);
-
  Newx(z, 1, MGWIZ);
 
- z->vtbl   = t;
+ z->vtable = vmg_vtable_dup(w->vtable);
  z->uvar   = w->uvar;
  z->opinfo = w->opinfo;
 
@@ -530,12 +608,8 @@ STATIC MGWIZ *vmg_mgwiz_clone(pTHX_ const MGWIZ *w) {
  VMG_CLONE_CB(len);
  VMG_CLONE_CB(clear);
  VMG_CLONE_CB(free);
-#if MGf_COPY
  VMG_CLONE_CB(copy);
-#endif /* MGf_COPY */
-#if MGf_DUP
  VMG_CLONE_CB(dup);
-#endif /* MGf_DUP */
 #if MGf_LOCAL
  VMG_CLONE_CB(local);
 #endif /* MGf_LOCAL */
@@ -611,12 +685,8 @@ STATIC MGVTBL vmg_wizard_vtbl = {
  NULL,            /* len */
  NULL,            /* clear */
  vmg_wizard_free, /* free */
-#if MGf_COPY
  NULL,            /* copy */
-#endif /* MGf_COPY */
-#if MGf_DUP
  NULL,            /* dup */
-#endif /* MGf_DUP */
 #if MGf_LOCAL
  NULL,            /* local */
 #endif /* MGf_LOCAL */
@@ -759,7 +829,7 @@ STATIC SV *vmg_data_get(pTHX_ SV *sv, const SV *wiz) {
 #define vmg_data_get(S, W) vmg_data_get(aTHX_ (S), (W))
  const MAGIC *mg = vmg_find(sv, wiz);
  return mg ? mg->mg_obj : NULL;
-} 
+}
 
 /* ... Magic cast/dispell .................................................. */
 
@@ -793,18 +863,16 @@ STATIC UV vmg_cast(pTHX_ SV *sv, const SV *wiz, SV **args, I32 items) {
 
  data = (w->cb_data) ? vmg_data_new(w->cb_data, sv, args, items) : NULL;
  /* sv_magicext() calls mg_magical and increments data's refcount */
- mg   = sv_magicext(sv, data, PERL_MAGIC_ext, w->vtbl,
+ mg   = sv_magicext(sv, data, PERL_MAGIC_ext, vmg_vtable_vtbl(w->vtable),
                               (const char *) wiz, HEf_SVKEY);
  SvREFCNT_dec(data);
  mg->mg_private = SIG_WIZ;
-#if MGf_COPY
  if (w->cb_copy)
   mg->mg_flags |= MGf_COPY;
-#endif /* MGf_COPY */
-#if 0 /* MGf_DUP */
+#if 0
  if (w->cb_dup)
   mg->mg_flags |= MGf_DUP;
-#endif /* MGf_DUP */
+#endif
 #if MGf_LOCAL
  if (w->cb_local)
   mg->mg_flags |= MGf_LOCAL;
@@ -972,18 +1040,14 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) {
 #define vmg_op_info_init(W) vmg_op_info_init(aTHX_ (W))
  switch (opinfo) {
   case VMG_OP_INFO_NAME:
-#if VMG_THREADSAFE
-   MUTEX_LOCK(&vmg_op_name_init_mutex);
-#endif
+   VMG_LOCK(&vmg_op_name_init_mutex);
    if (!vmg_op_name_init) {
     OPCODE t;
     for (t = 0; t < OP_max; ++t)
      vmg_op_name_len[t] = strlen(PL_op_name[t]);
     vmg_op_name_init = 1;
    }
-#if VMG_THREADSAFE
-   MUTEX_UNLOCK(&vmg_op_name_init_mutex);
-#endif
+   VMG_UNLOCK(&vmg_op_name_init_mutex);
    break;
   case VMG_OP_INFO_OBJECT: {
    dMY_CXT;
@@ -1204,7 +1268,6 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  return ret;
 }
 
-#if MGf_COPY
 STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key,
 # if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) || VMG_HAS_PERL(5, 12, 0)
   I32 keylen
@@ -1230,13 +1293,12 @@ STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key,
 
  return ret;
 }
-#endif /* MGf_COPY */
 
-#if 0 /*  MGf_DUP */
+#if 0
 STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
  return 0;
 }
-#endif /* MGf_DUP */
+#endif
 
 #if MGf_LOCAL
 STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
@@ -1377,6 +1439,7 @@ BOOT:
 #endif
  MY_CXT.b__op_stashes[0] = NULL;
 #if VMG_THREADSAFE
+ MUTEX_INIT(&vmg_vtable_refcount_mutex);
  MUTEX_INIT(&vmg_op_name_init_mutex);
  call_atexit(vmg_cleanup, NULL);
 #endif
@@ -1444,20 +1507,13 @@ SV *_wizard(...)
 PROTOTYPE: DISABLE
 PREINIT:
  I32 i = 0;
- UV opinfo;
  MGWIZ *w;
  MGVTBL *t;
- SV *cb;
+ SV *cb, *op_info, *copy_key;
 CODE:
  dMY_CXT;
 
- if (items != 7
-#if MGf_COPY
-              + 1
-#endif /* MGf_COPY */
-#if MGf_DUP
-              + 1
-#endif /* MGf_DUP */
+ if (items != 9
 #if MGf_LOCAL
               + 1
 #endif /* MGf_LOCAL */
@@ -1466,31 +1522,22 @@ CODE:
 #endif /* VMG_UVAR */
               ) { croak(vmg_wrongargnum); }
 
- Newx(t, 1, MGVTBL);
- Newx(w, 1, MGWIZ);
+ op_info = ST(i++);
+ w = vmg_mgwiz_alloc(SvOK(op_info) ? SvUV(op_info) : 0);
+ t = vmg_vtable_vtbl(w->vtable);
 
  VMG_SET_CB(ST(i++), data);
 
- cb = ST(i++);
- opinfo = SvOK(cb) ? SvUV(cb) : 0;
- w->opinfo = (U8) ((opinfo < 255) ? opinfo : 255);
- if (w->opinfo)
-  vmg_op_info_init(w->opinfo);
-
  VMG_SET_SVT_CB(ST(i++), get);
  VMG_SET_SVT_CB(ST(i++), set);
  VMG_SET_SVT_CB(ST(i++), len);
  VMG_SET_SVT_CB(ST(i++), clear);
  VMG_SET_SVT_CB(ST(i++), free);
-#if MGf_COPY
  VMG_SET_SVT_CB(ST(i++), copy);
-#endif /* MGf_COPY */
-#if MGf_DUP
  /* VMG_SET_SVT_CB(ST(i++), dup); */
  i++;
  t->svt_dup = NULL;
  w->cb_dup  = NULL;
-#endif /* MGf_DUP */
 #if MGf_LOCAL
  VMG_SET_SVT_CB(ST(i++), local);
 #endif /* MGf_LOCAL */
@@ -1499,16 +1546,14 @@ CODE:
  VMG_SET_CB(ST(i++), store);
  VMG_SET_CB(ST(i++), exists);
  VMG_SET_CB(ST(i++), delete);
- cb = ST(i++);
+
+ copy_key = ST(i++);
  if (w->cb_fetch || w->cb_store || w->cb_exists || w->cb_delete)
-  w->uvar = SvTRUE(cb) ? 2 : 1;
- else
-  w->uvar = 0;
+  w->uvar = SvTRUE(copy_key) ? 2 : 1;
 #endif /* VMG_UVAR */
 #if VMG_MULTIPLICITY
  w->owner = aTHX;
 #endif /* VMG_MULTIPLICITY */
- w->vtbl  = t;
 #if VMG_THREADSAFE
  ptable_store(MY_CXT.wizards, w, w);
 #endif /* VMG_THREADSAFE */