// ffi-objc-arc-00b — multi-instance allocator threading.
//
// Verifies that EACH sx-defined-class instance captures its own
// allocator and round-trips through it. Catches bugs where:
//   - the captured allocator is shared across instances (one global
//     slot instead of per-instance).
//   - alloc captures the wrong allocator on the 2nd+ instance.
//   - dealloc reads garbage if state[0] is overwritten between
//     instances.
//
// Three instances → three alloc events → three dealloc events. The
// tracker observes exactly +3 / +3 deltas.

#import "modules/std.sx";
#import "modules/std/mem.sx";
#import "modules/ffi/objc.sx";
#import "modules/build.sx";

SxMultiProbe :: #objc_class("SxMultiProbe") {
    #extends NSObject;
    a: i32;
    b: i32;
    alloc :: () -> *SxMultiProbe;
}

main :: () -> i32 {
    inline if OS == .macos {
        gpa := GPA.init();
        tracker := TrackingAllocator.init(xx gpa);

        push Context.{ allocator = xx tracker, data = null } {
            alloc_before   := tracker.alloc_count;
            dealloc_before := tracker.dealloc_count;

            f1 := SxMultiProbe.alloc();
            f2 := SxMultiProbe.alloc();
            f3 := SxMultiProbe.alloc();

            alloc_after_three := tracker.alloc_count - alloc_before;

            f1.release();
            f2.release();
            f3.release();

            alloc_delta   := tracker.alloc_count   - alloc_before;
            dealloc_delta := tracker.dealloc_count - dealloc_before;

            // alloc_delta MAY include extras from autorelease/etc. but
            // each SxMultiProbe.alloc contributes at least 1. Check the
            // BALANCE: every alloc paired with a dealloc.
            if dealloc_delta != alloc_delta {
                print("FAIL: alloc/dealloc unbalanced; alloc={} dealloc={}\n",
                      alloc_delta, dealloc_delta);
                return 1;
            }
            if alloc_after_three < 3 {
                print("FAIL: 3 SxMultiProbe.alloc()s should produce >= 3 tracker allocs; saw {}\n",
                      alloc_after_three);
                return 1;
            }
            if dealloc_delta < 3 {
                print("FAIL: 3 release()s should produce >= 3 tracker deallocs; saw {}\n",
                      dealloc_delta);
                return 1;
            }
        }

        print("multi-instance round-trip: ok\n");
    }
    inline if OS != .macos {
        print("skipped (not macos)\n");
    }
    0
}
