+/* ... 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
+