From: Vincent Pit Date: Mon, 31 May 2010 22:26:41 +0000 (+0200) Subject: Fix the thread destructor trick for 5.13.1 X-Git-Tag: v0.04~2 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FThread-Cleanup.git;a=commitdiff_plain;h=a518962799a5d83550da2be0f469ff665edbbb81 Fix the thread destructor trick for 5.13.1 --- diff --git a/Cleanup.xs b/Cleanup.xs index f41b2c8..0a19890 100644 --- a/Cleanup.xs +++ b/Cleanup.xs @@ -11,49 +11,23 @@ #define TC_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) -#undef ENTERn -#if defined(ENTER_with_name) && !TC_HAS_PERL(5, 11, 4) -# define ENTERn(N) ENTER_with_name(N) -#else -# define ENTERn(N) ENTER -#endif - -#undef LEAVEn -#if defined(LEAVE_with_name) && !TC_HAS_PERL(5, 11, 4) -# define LEAVEn(N) LEAVE_with_name(N) -#else -# define LEAVEn(N) LEAVE -#endif - -STATIC void tc_callback(pTHX_ void *); +#include "reap.h" STATIC void tc_callback(pTHX_ void *ud) { - int *level = ud; - SV *id; - - if (*level) { - *level = 0; - LEAVE; - SAVEDESTRUCTOR_X(tc_callback, level); - ENTER; - } else { - dSP; + dSP; - PerlMemShared_free(level); + ENTER; + SAVETMPS; - ENTER; - SAVETMPS; + PUSHMARK(SP); + PUTBACK; - PUSHMARK(SP); - PUTBACK; + call_pv(__PACKAGE__ "::_CLEANUP", G_VOID | G_EVAL); - call_pv(__PACKAGE__ "::_CLEANUP", G_VOID | G_EVAL); + PUTBACK; - PUTBACK; - - FREETMPS; - LEAVE; - } + FREETMPS; + LEAVE; } MODULE = Thread::Cleanup PACKAGE = Thread::Cleanup @@ -63,12 +37,7 @@ PROTOTYPES: DISABLE void CLONE(...) PREINIT: - int *level; CODE: { - level = PerlMemShared_malloc(sizeof *level); - *level = 1; - LEAVEn("sub"); - SAVEDESTRUCTOR_X(tc_callback, level); - ENTERn("sub"); + reap(3, tc_callback, NULL); } diff --git a/MANIFEST b/MANIFEST index fed10b4..07996e3 100644 --- a/MANIFEST +++ b/MANIFEST @@ -4,6 +4,7 @@ MANIFEST Makefile.PL README lib/Thread/Cleanup.pm +reap.h samples/try.pl t/00-load.t t/10-join.t diff --git a/reap.h b/reap.h new file mode 100644 index 0000000..6b92167 --- /dev/null +++ b/reap.h @@ -0,0 +1,81 @@ +/* This file is part of the Thread::Cleanup Perl module. + * See http://search.cpan.org/dist/Thread-Cleanup/ */ + +/* This header provides a specialized version of Scope::Upper::reap that can be + * called directly from XS. + * See http://search.cpan.org/dist/Scope-Upper/ for details. */ + +#ifndef REAP_H +#define REAP_H 1 + +#define REAP_DESTRUCTOR_SIZE 3 + +typedef struct { + I32 depth; + I32 *origin; + void (*cb)(pTHX_ void *); + void *ud; + char *dummy; +} reap_ud; + +STATIC void reap_pop(pTHX_ void *); + +STATIC void reap_pop(pTHX_ void *ud_) { + reap_ud *ud = ud_; + I32 depth, *origin, mark, base; + + depth = ud->depth; + origin = ud->origin; + mark = origin[depth]; + base = origin[depth - 1]; + + if (base < mark) { + PL_savestack_ix = mark; + leave_scope(base); + } + PL_savestack_ix = base; + + if ((ud->depth = --depth) > 0) { + SAVEDESTRUCTOR_X(reap_pop, ud); + } else { + void (*cb)(pTHX_ void *) = ud->cb; + void *cb_ud = ud->ud; + + PerlMemShared_free(ud->origin); + PerlMemShared_free(ud); + + SAVEDESTRUCTOR_X(cb, cb_ud); + } +} + +STATIC void reap(pTHX_ I32 depth, void (*cb)(pTHX_ void *), void *cb_ud) { +#define reap(D, CB, UD) reap(aTHX_ (D), (CB), (UD)) + reap_ud *ud; + I32 i; + + if (depth > PL_scopestack_ix) + depth = PL_scopestack_ix; + + ud = PerlMemShared_malloc(sizeof *ud); + ud->depth = depth; + ud->origin = PerlMemShared_malloc((depth + 1) * sizeof *ud->origin); + ud->cb = cb; + ud->ud = cb_ud; + ud->dummy = NULL; + + for (i = depth; i >= 1; --i) { + I32 j = PL_scopestack_ix - i; + ud->origin[depth - i] = PL_scopestack[j]; + PL_scopestack[j] += REAP_DESTRUCTOR_SIZE; + } + ud->origin[depth] = PL_savestack_ix; + + while (PL_savestack_ix + REAP_DESTRUCTOR_SIZE + <= PL_scopestack[PL_scopestack_ix - 1]) { + save_pptr(&ud->dummy); + } + + SAVEDESTRUCTOR_X(reap_pop, ud); +} + +#endif /* REAP_H */