import Foundation

@main

struct App {

    static func main() {

        class Warehouse {

            var stock: Int = 10

        }

        let warehouse = Warehouse()

        let semStartB = DispatchSemaphore(value: 0)

        let semBFinishedRead = DispatchSemaphore(value: 0)

        let semAFinishedCart = DispatchSemaphore(value: 0)

        let semBFinishedUpdate = DispatchSemaphore(value: 0)

        let semDone = DispatchSemaphore(value: 0)

        Thread.detachNewThread {

            let localStockA = warehouse.stock

            print("Thread A liest den Lagerbestand (\(localStockA) Stück)")

            semStartB.signal()

            semBFinishedRead.wait()

            print("Thread A legt Smartphone in den Warenkorb")

            let newStockA = localStockA - 1

            semAFinishedCart.signal()

            semBFinishedUpdate.wait()

            warehouse.stock = newStockA

            print(

                "Thread A aktualisiert den Lagerbestand auf \(warehouse.stock) Stück (\(localStockA) Stück - 1 Stück)"

            )

            semDone.signal()

        }

        Thread.detachNewThread {

            semStartB.wait()

            let localStockB = warehouse.stock

            print("Thread B liest den Lagerbestand (\(localStockB) Stück)")

            print("Thread B legt 2 Smartphones in den Warenkorb")

            let newStockB = localStockB - 2

            semBFinishedRead.signal()

            semAFinishedCart.wait()

            warehouse.stock = newStockB

            print(

                "Thread B aktualisiert den Lagerbestand auf \(warehouse.stock) Stück (\(localStockB) Stück - 2 Stück)"

            )

            semBFinishedUpdate.signal()

            semDone.signal()

        }

        semDone.wait()

        semDone.wait()

        print("Endgültiger Lagerbestand im System: \(warehouse.stock) Stück")

    }

}
