+uint gc_getAttr(void* p)
+{
+ if (p is null)
+ return 0;
+ return locked!(uint, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ Pool* pool = findPool(p);
+ if (pool is null)
+ return 0u;
+ auto bit_i = cast(size_t)(p - pool.baseAddr) / 16;
+ return getAttr(pool, bit_i);
+ })();
+}
+
+uint gc_setAttr(void* p, uint attrs)
+{
+ if (p is null)
+ return 0;
+ return locked!(uint, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ Pool* pool = findPool(p);
+ if (pool is null)
+ return 0u;
+ auto bit_i = cast(size_t)(p - pool.baseAddr) / 16;
+ uint old_attrs = getAttr(pool, bit_i);
+ setAttr(pool, bit_i, attrs);
+ return old_attrs;
+ })();
+}
+
+uint gc_clrAttr(void* p, uint attrs)
+{
+ if (p is null)
+ return 0;
+ return locked!(uint, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ Pool* pool = findPool(p);
+ if (pool is null)
+ return 0u;
+ auto bit_i = cast(size_t)(p - pool.baseAddr) / 16;
+ uint old_attrs = getAttr(pool, bit_i);
+ clrAttr(pool, bit_i, attrs);
+ return old_attrs;
+ })();
+}
+
+void* gc_malloc(size_t size, uint attrs = 0,
+ PointerMap ptrmap = PointerMap.init)
+{
+ if (size == 0)
+ return null;
+ return locked!(void*, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return malloc(size, attrs, ptrmap.bits.ptr);
+ })();
+}
+
+void* gc_calloc(size_t size, uint attrs = 0,
+ PointerMap ptrmap = PointerMap.init)
+{
+ if (size == 0)
+ return null;
+ return locked!(void*, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return calloc(size, attrs, ptrmap.bits.ptr);
+ })();
+}
+
+void* gc_realloc(void* p, size_t size, uint attrs = 0,
+ PointerMap ptrmap = PointerMap.init)
+{
+ return locked!(void*, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return realloc(p, size, attrs, ptrmap.bits.ptr);
+ })();
+}
+
+size_t gc_extend(void* p, size_t min_size, size_t max_size)
+{
+ return locked!(size_t, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return extend(p, min_size, max_size);
+ })();
+}
+
+size_t gc_reserve(size_t size)
+{
+ if (size == 0)
+ return 0;
+ return locked!(size_t, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return reserve(size);
+ })();
+}
+
+void gc_free(void* p)
+{
+ if (p is null)
+ return;
+ return locked!(void, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ free(p);
+ })();
+}
+
+void* gc_addrOf(void* p)
+{
+ if (p is null)
+ return null;
+ return locked!(void*, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ Pool* pool = findPool(p);
+ if (pool is null)
+ return null;
+ return pool.findBase(p);
+ })();
+}
+
+size_t gc_sizeOf(void* p)
+{
+ if (p is null)
+ return 0;
+ return locked!(size_t, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return sizeOf(p);
+ })();
+}
+
+BlkInfo gc_query(void* p)
+{
+ if (p is null)
+ return BlkInfo.init;
+ return locked!(BlkInfo, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return getInfo(p);
+ })();
+}
+
+// NOTE: This routine is experimental. The stats or function name may change
+// before it is made officially available.
+GCStats gc_stats()
+{
+ return locked!(GCStats, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ return getStats();
+ })();
+}
+
+void gc_addRoot(void* p)
+{
+ if (p is null)
+ return;
+ return locked!(void, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ if (gc.roots.append(p) is null)
+ onOutOfMemoryError();
+ })();
+}
+
+void gc_addRange(void* p, size_t size)
+{
+ if (p is null || size == 0)
+ return;
+ return locked!(void, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ if (gc.ranges.append(Range(p, p + size)) is null)
+ onOutOfMemoryError();
+ })();
+}
+
+void gc_removeRoot(void* p)
+{
+ if (p is null)
+ return;
+ return locked!(void, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ bool r = gc.roots.remove(p);
+ assert (r);
+ })();
+}
+
+void gc_removeRange(void* p)
+{
+ if (p is null)
+ return;
+ return locked!(void, () {
+ assert (Invariant()); scope (exit) assert (Invariant());
+ bool r = gc.ranges.remove(Range(p, null));
+ assert (r);
+ })();
+}
+
+void* gc_weakpointerCreate(Object r)
+{
+ // weakpointers do their own locking
+ return weakpointerCreate(r);
+}
+
+void gc_weakpointerDestroy(void* wp)
+{
+ // weakpointers do their own locking
+ weakpointerDestroy(wp);
+}
+
+Object gc_weakpointerGet(void* wp)
+{
+ // weakpointers do their own locking
+ return weakpointerGet(wp);