Replace check functions in a thread-safe way
authorVincent Pit <vince@profvince.com>
Tue, 26 Feb 2013 16:35:11 +0000 (13:35 -0300)
committerVincent Pit <vince@profvince.com>
Tue, 26 Feb 2013 16:35:11 +0000 (13:35 -0300)
indirect.xs

index e196119..d3d1e00 100644 (file)
 # define MY_CXT_CLONE NOOP
 #endif
 
+#if defined(OP_CHECK_MUTEX_LOCK) && defined(OP_CHECK_MUTEX_UNLOCK)
+# define I_CHECK_MUTEX_LOCK   OP_CHECK_MUTEX_LOCK
+# define I_CHECK_MUTEX_UNLOCK OP_CHECK_MUTEX_UNLOCK
+#else
+# define I_CHECK_MUTEX_LOCK   OP_REFCNT_LOCK
+# define I_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK
+#endif
+
+typedef OP *(*indirect_ck_t)(pTHX_ OP *);
+
+#ifdef wrap_op_checker
+
+# define indirect_ck_replace(T, NC, OCP) wrap_op_checker((T), (NC), (OCP))
+
+#else
+
+STATIC void indirect_ck_replace(pTHX_ OPCODE type, indirect_ck_t new_ck, indirect_ck_t *old_ck_p) {
+#define indirect_ck_replace(T, NC, OCP) indirect_ck_replace(aTHX_ (T), (NC), (OCP))
+ I_CHECK_MUTEX_LOCK;
+ if (!*old_ck_p) {
+  *old_ck_p      = PL_check[type];
+  PL_check[type] = new_ck;
+ }
+ I_CHECK_MUTEX_UNLOCK;
+}
+
+#endif
+
+STATIC void indirect_ck_restore(pTHX_ OPCODE type, indirect_ck_t *old_ck_p) {
+#define indirect_ck_restore(T, OCP) indirect_ck_restore(aTHX_ (T), (OCP))
+ I_CHECK_MUTEX_LOCK;
+ if (*old_ck_p) {
+  PL_check[type] = *old_ck_p;
+  *old_ck_p      = 0;
+ }
+ I_CHECK_MUTEX_UNLOCK;
+}
+
 /* --- Helpers ------------------------------------------------------------- */
 
 /* ... Thread-safe hints ................................................... */
@@ -871,23 +909,15 @@ STATIC void indirect_teardown(pTHX_ void *root) {
 #endif
  }
 
- PL_check[OP_CONST]           = MEMBER_TO_FPTR(indirect_old_ck_const);
- indirect_old_ck_const        = 0;
- PL_check[OP_RV2SV]           = MEMBER_TO_FPTR(indirect_old_ck_rv2sv);
- indirect_old_ck_rv2sv        = 0;
- PL_check[OP_PADANY]          = MEMBER_TO_FPTR(indirect_old_ck_padany);
- indirect_old_ck_padany       = 0;
- PL_check[OP_SCOPE]           = MEMBER_TO_FPTR(indirect_old_ck_scope);
- indirect_old_ck_scope        = 0;
- PL_check[OP_LINESEQ]         = MEMBER_TO_FPTR(indirect_old_ck_lineseq);
- indirect_old_ck_lineseq      = 0;
-
- PL_check[OP_METHOD]          = MEMBER_TO_FPTR(indirect_old_ck_method);
- indirect_old_ck_method       = 0;
- PL_check[OP_METHOD_NAMED]    = MEMBER_TO_FPTR(indirect_old_ck_method_named);
- indirect_old_ck_method_named = 0;
- PL_check[OP_ENTERSUB]        = MEMBER_TO_FPTR(indirect_old_ck_entersub);
- indirect_old_ck_entersub     = 0;
+ indirect_ck_restore(OP_CONST,   &indirect_old_ck_const);
+ indirect_ck_restore(OP_RV2SV,   &indirect_old_ck_rv2sv);
+ indirect_ck_restore(OP_PADANY,  &indirect_old_ck_padany);
+ indirect_ck_restore(OP_SCOPE,   &indirect_old_ck_scope);
+ indirect_ck_restore(OP_LINESEQ, &indirect_old_ck_lineseq);
+
+ indirect_ck_restore(OP_METHOD,       &indirect_old_ck_method);
+ indirect_ck_restore(OP_METHOD_NAMED, &indirect_old_ck_method_named);
+ indirect_ck_restore(OP_ENTERSUB,     &indirect_old_ck_entersub);
 
  indirect_initialized = 0;
 }
@@ -907,23 +937,18 @@ STATIC void indirect_setup(pTHX) {
   MY_CXT.global_code = NULL;
  }
 
- indirect_old_ck_const        = PL_check[OP_CONST];
- PL_check[OP_CONST]           = MEMBER_TO_FPTR(indirect_ck_const);
- indirect_old_ck_rv2sv        = PL_check[OP_RV2SV];
- PL_check[OP_RV2SV]           = MEMBER_TO_FPTR(indirect_ck_rv2sv);
- indirect_old_ck_padany       = PL_check[OP_PADANY];
- PL_check[OP_PADANY]          = MEMBER_TO_FPTR(indirect_ck_padany);
- indirect_old_ck_scope        = PL_check[OP_SCOPE];
- PL_check[OP_SCOPE]           = MEMBER_TO_FPTR(indirect_ck_scope);
- indirect_old_ck_lineseq      = PL_check[OP_LINESEQ];
- PL_check[OP_LINESEQ]         = MEMBER_TO_FPTR(indirect_ck_scope);
-
- indirect_old_ck_method       = PL_check[OP_METHOD];
- PL_check[OP_METHOD]          = MEMBER_TO_FPTR(indirect_ck_method);
- indirect_old_ck_method_named = PL_check[OP_METHOD_NAMED];
- PL_check[OP_METHOD_NAMED]    = MEMBER_TO_FPTR(indirect_ck_method_named);
- indirect_old_ck_entersub     = PL_check[OP_ENTERSUB];
- PL_check[OP_ENTERSUB]        = MEMBER_TO_FPTR(indirect_ck_entersub);
+ indirect_ck_replace(OP_CONST,   indirect_ck_const,  &indirect_old_ck_const);
+ indirect_ck_replace(OP_RV2SV,   indirect_ck_rv2sv,  &indirect_old_ck_rv2sv);
+ indirect_ck_replace(OP_PADANY,  indirect_ck_padany, &indirect_old_ck_padany);
+ indirect_ck_replace(OP_SCOPE,   indirect_ck_scope,  &indirect_old_ck_scope);
+ indirect_ck_replace(OP_LINESEQ, indirect_ck_scope,  &indirect_old_ck_lineseq);
+
+ indirect_ck_replace(OP_METHOD,       indirect_ck_method,
+                                      &indirect_old_ck_method);
+ indirect_ck_replace(OP_METHOD_NAMED, indirect_ck_method_named,
+                                      &indirect_old_ck_method_named);
+ indirect_ck_replace(OP_ENTERSUB,     indirect_ck_entersub,
+                                      &indirect_old_ck_entersub);
 
 #if I_MULTIPLICITY
  call_atexit(indirect_teardown, aTHX);