' Slab allocator for fixed-size objects with partial/empty/full list management
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL i  AS LONG
    LOCAL j  AS LONG
    LOCAL slabCount  AS LONG
    LOCAL objSize  AS LONG
    LOCAL slabsPerPage  AS LONG
    LOCAL pageSize  AS LONG
    LOCAL totalObjs  AS LONG
    LOCAL freeCount  AS LONG
    LOCAL allocCount  AS LONG
    LOCAL slabFree(20) AS LONG
    LOCAL slabUsed(20) AS LONG
    LOCAL slabTotal(20) AS LONG
    LOCAL slabState(20) AS LONG
    LOCAL objMap(400) AS LONG
    LOCAL alloced(400) AS LONG
    LOCAL allocedCount AS LONG
    LOCAL numSlabs  AS LONG
    LOCAL currentSlab  AS LONG
    LOCAL objIdx  AS LONG
    LOCAL foundSlab  AS LONG
    LOCAL bestSlab  AS LONG
    LOCAL partialCount  AS LONG
    LOCAL emptyCount  AS LONG
    LOCAL fullCount  AS LONG
    LOCAL ops(100) AS LONG
    LOCAL opCount  AS LONG
    LOCAL opType  AS LONG
    LOCAL opParam  AS LONG
    LOCAL freedObj  AS LONG
    LOCAL temp  AS LONG
    pageSize = 4096
    objSize = 64
    slabsPerPage = pageSize / objSize
    numSlabs = 5

    PRINT "=== Slab Allocator Simulator ==="
    PRINT "Page size:" & STR$(pageSize) & " bytes"
    PRINT "Object size:" & STR$(objSize) & " bytes"
    PRINT "Objects per slab:" & STR$(slabsPerPage)
    PRINT

    totalObjs = 0
    allocCount = 0
    freeCount = 0

    FOR i = 0 TO numSlabs - 1
        slabTotal(i) = slabsPerPage
        slabFree(i) = slabsPerPage
        slabUsed(i) = 0
        slabState(i) = 0
        totalObjs = totalObjs + slabsPerPage
    NEXT i

    PRINT "Initialized" & STR$(numSlabs) & " slabs, total objects:" & STR$(totalObjs)
    PRINT

    opCount = 15
    ops(0) = 1
    ops(1) = 1
    ops(2) = 1
    ops(3) = 1
    ops(4) = 1
    ops(5) = 1
    ops(6) = 1
    ops(7) = 1
    ops(8) = 2
    ops(9) = 1
    ops(10) = 1
    ops(11) = 2
    ops(12) = 1
    ops(13) = 1
    ops(14) = 2

    FOR i = 0 TO opCount - 1
        opType = ops(i)
        IF opType = 1 THEN
            foundSlab = -1
            bestSlab = -1

            FOR j = 0 TO numSlabs - 1
                IF slabFree(j) > 0 AND slabUsed(j) < slabTotal(j) THEN
                    IF slabFree(j) > 0 AND slabState(j) = 0 THEN
                        bestSlab = j
                        GOTO foundPartial
                    END IF
                END IF
            NEXT j

            FOR j = 0 TO numSlabs - 1
                IF slabFree(j) = slabTotal(j) THEN
                    bestSlab = j
                    GOTO foundPartial
                END IF
            NEXT j

            GOTO allocDone
foundPartial:
            foundSlab = bestSlab
            IF slabFree(foundSlab) = slabTotal(foundSlab) THEN
                slabState(foundSlab) = 0
            END IF

            slabFree(foundSlab) = slabFree(foundSlab) - 1
            slabUsed(foundSlab) = slabUsed(foundSlab) + 1

            objIdx = allocCount
            alloced(allocCount) = foundSlab
            allocCount = allocCount + 1

            PRINT "ALLOC obj" & STR$(objIdx) & " from slab" & STR$(foundSlab) & " (free:" & STR$(slabFree(foundSlab)) & ", used:" & STR$(slabUsed(foundSlab)) & ")"

            IF slabFree(foundSlab) = 0 THEN
                slabState(foundSlab) = 1
                PRINT "  -> Slab" & STR$(foundSlab) & " now FULL"
            END IF
        ELSE
            IF allocCount > 0 THEN
                freedObj = allocCount - 1
                IF freedObj >= 0 THEN
                    foundSlab = alloced(freedObj)
                    alloced(freedObj) = allocCount - 1
                    allocCount = allocCount - 1

                    slabFree(foundSlab) = slabFree(foundSlab) + 1
                    slabUsed(foundSlab) = slabUsed(foundSlab) - 1
                    freeCount = freeCount + 1

                    PRINT "FREE  obj from slab" & STR$(foundSlab) & " (free:" & STR$(slabFree(foundSlab)) & ", used:" & STR$(slabUsed(foundSlab)) & ")"

                    IF slabFree(foundSlab) = slabTotal(foundSlab) THEN
                        slabState(foundSlab) = 2
                        PRINT "  -> Slab" & STR$(foundSlab) & " now EMPTY"
                    ELSE
                        slabState(foundSlab) = 0
                    END IF
                END IF
            ELSE
                PRINT "FREE  skipped: no allocated objects"
            END IF
        END IF
allocDone:
    NEXT i

    PRINT
    PRINT "=== Slab Summary ==="
    partialCount = 0
    emptyCount = 0
    fullCount = 0
    FOR i = 0 TO numSlabs - 1
        IF slabState(i) = 0 THEN
            partialCount = partialCount + 1
            PRINT "Slab" & STR$(i) & ": PARTIAL (free:" & STR$(slabFree(i)) & "/" & STR$(slabTotal(i)) & ")"
        ELSE
            IF slabState(i) = 1 THEN
                fullCount = fullCount + 1
                PRINT "Slab" & STR$(i) & ": FULL (used:" & STR$(slabUsed(i)) & "/" & STR$(slabTotal(i)) & ")"
            ELSE
                emptyCount = emptyCount + 1
                PRINT "Slab" & STR$(i) & ": EMPTY (free:" & STR$(slabFree(i)) & "/" & STR$(slabTotal(i)) & ")"
            END IF
        END IF
    NEXT i
    PRINT
    PRINT "Partial slabs:" & STR$(partialCount)
    PRINT "Full slabs:" & STR$(fullCount)
    PRINT "Empty slabs:" & STR$(emptyCount)
    PRINT "Total allocs:" & STR$(allocCount)
    PRINT "Total frees:" & STR$(freeCount)
    PRINT "Slab allocator simulation complete."

    FUNCTION = 0
END FUNCTION
