+STATIC U32 rep_initialized = 0;
+
+STATIC void rep_teardown(pTHX_ void *root) {
+ if (!rep_initialized || aTHX != root)
+ return;
+
+ {
+ dMY_CXT;
+ ptable_free(MY_CXT.tbl);
+ }
+
+ rep_initialized = 0;
+}
+
+STATIC void rep_setup(pTHX) {
+#define rep_setup() rep_setup(aTHX)
+ if (rep_initialized)
+ return;
+
+ {
+ MY_CXT_INIT;
+ MY_CXT.tbl = ptable_new();
+ MY_CXT.owner = aTHX;
+ }
+
+ call_atexit(rep_teardown, aTHX);
+
+ rep_initialized = 1;
+}
+
+#else /* REP_THREADSAFE */
+
+#define rep_setup()
+
+#endif /* !REP_THREADSAFE */
+
+STATIC U32 rep_booted = 0;
+
+/* --- XS ------------------------------------------------------------------ */
+
+MODULE = re::engine::Plugin PACKAGE = re::engine::Plugin
+
+PROTOTYPES: DISABLE
+
+BOOT:
+{
+ if (!rep_booted++) {
+ HV *stash;
+
+ PERL_HASH(rep_hash, __PACKAGE__, __PACKAGE_LEN__);
+
+ stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1);
+ newCONSTSUB(stash, "REP_THREADSAFE", newSVuv(REP_THREADSAFE));
+ newCONSTSUB(stash, "REP_FORKSAFE", newSVuv(REP_FORKSAFE));
+ }
+
+ rep_setup();
+}
+
+#if REP_THREADSAFE
+
+void
+CLONE(...)
+PREINIT:
+ ptable *t;
+PPCODE:
+ {
+ rep_ptable_clone_ud ud;
+ dMY_CXT;
+
+ t = ptable_new();
+ rep_ptable_clone_ud_init(ud, t, MY_CXT.owner);
+ ptable_walk(MY_CXT.tbl, rep_ptable_clone, &ud);
+ rep_ptable_clone_ud_deinit(ud);
+ }
+ {
+ MY_CXT_CLONE;
+ MY_CXT.tbl = t;
+ MY_CXT.owner = aTHX;
+ }
+ reap(3, rep_thread_cleanup, NULL);
+ XSRETURN(0);
+
+#endif /* REP_THREADSAFE */
+
+void