Task: Banker's algorithm




Go: package bank

import (
    "bytes"
    "errors"
    "fmt"
    "log"
    "sort"
    "sync"
)

type PID string
type RID string
type RMap map[RID]int


func (m RMap) String() string {
    rs := make([]string, len(m))
    i := 0
    for r := range m {
        rs[i] = string(r)
        i++
    }
    sort.Strings(rs)
    var b bytes.Buffer
    b.WriteString("{")
    for _, r := range rs {
        fmt.Fprintf(&b, "%q: %d, ", r, m[RID(r)])
    }
    bb := b.Bytes()
    if len(bb) > 1 {
        bb[len(bb)-2] = '}'
    }
    return string(bb)
}

type Bank struct {
    available  RMap
    max        map[PID]RMap
    allocation map[PID]RMap
    sync.Mutex
}

func (b *Bank) need(p PID, r RID) int {
    return b.max[p][r] - b.allocation[p][r]
}

func New(available RMap) (b *Bank, err error) {
    for r, a := range available {
        if a < 0 {
            return nil, fmt.Errorf("negative resource %s: %d", r, a)
        }
    }
    return &Bank{
        available:  available,
        max:        map[PID]RMap{},
        allocation: map[PID]RMap{},
    }, nil
}

func (b *Bank) NewProcess(p PID, max RMap) (err error) {
    b.Lock()
    defer b.Unlock()
    if _, ok := b.max[p]; ok {
        return fmt.Errorf("process %s already registered", p)
    }
    for r, m := range max {
        switch a, ok := b.available[r]; {
        case !ok:
            return fmt.Errorf("resource %s unknown", r)
        case m > a:
            return fmt.Errorf("resource %s: process %s max %d > available %d",
                r, p, m, a)
        }
    }
    b.max[p] = max
    b.allocation[p] = RMap{}
    return
}

func (b *Bank) Request(pid PID, change RMap) (err error) {
    b.Lock()
    defer b.Unlock()
    if _, ok := b.max[pid]; !ok {
        return fmt.Errorf("process %s unknown", pid)
    }
    for r, c := range change {
        if c < 0 {
            return errors.New("decrease not allowed")
        }
        if _, ok := b.available[r]; !ok {
            return fmt.Errorf("resource %s unknown", r)
        }
        if c > b.need(pid, r) {
            return errors.New("increase exceeds declared max")
        }
    }
    
    
    for r, c := range change {
        b.allocation[pid][r] += c 
    }
    defer func() {
        if err != nil { 
            for r, c := range change {
                b.allocation[pid][r] -= c 
            }
        }
    }()
    
    
    cash := RMap{}
    for r, a := range b.available {
        cash[r] = a
    }
    perm := make([]PID, len(b.allocation))
    i := 1
    for pr, a := range b.allocation {
        if pr == pid {
            perm[0] = pr
        } else {
            perm[i] = pr
            i++
        }
        for r, a := range a {
            cash[r] -= a
        }
    }
    ret := RMap{}  
    m := len(perm) 
    for {
        
        h := 0
    h:
        for ; ; h++ {
            if h == m {
                
                return errors.New("request would make deadlock possible")
            }
            for r := range b.available {
                if b.need(perm[h], r) > cash[r]+ret[r] {
                    
                    continue h
                }
            }
            
            log.Println(" ", perm[h], "could terminate")
            
            break
        }
        if h == 0 { 
            
            
            return nil
        }
        for r, a := range b.allocation[perm[h]] {
            ret[r] += a
        }
        m--
        perm[h] = perm[m]
    }
}




Python: def main():
    resources = int(input("Cantidad de recursos: "))
    processes = int(input("Cantidad de procesos: "))
    max_resources = [int(i) for i in input("Recursos máximos: ").split()]

    print("\n-- recursos asignados para cada proceso  --")
    currently_allocated = [[int(i) for i in input(f"proceso {j + 1}: ").split()] for j in range(processes)]

    print("\n--- recursos máximos para cada proceso  ---")
    max_need = [[int(i) for i in input(f"proceso {j + 1}: ").split()] for j in range(processes)]

    allocated = [0] * resources
    for i in range(processes):
        for j in range(resources):
            allocated[j] += currently_allocated[i][j]
    print(f"\nRecursos totales asignados  : {allocated}")

    available = [max_resources[i] - allocated[i] for i in range(resources)]
    print(f"Recursos totales disponibles: {available}\n")

    running = [True] * processes
    count = processes
    while count != 0:
        safe = False
        for i in range(processes):
            if running[i]:
                executing = True
                for j in range(resources):
                    if max_need[i][j] - currently_allocated[i][j] > available[j]:
                        executing = False
                        break
                if executing:
                    print(f"proceso {i + 1} ejecutándose")
                    running[i] = False
                    count -= 1
                    safe = True
                    for j in range(resources):
                        available[j] += currently_allocated[i][j]
                    break
        if not safe:
            print("El proceso está en un estado inseguro.")
            break

        print(f"El proceso está en un estado seguro.\nRecursos disponibles: {available}\n")


if __name__ == '__main__':
    main()