Skip to content

Instantly share code, notes, and snippets.

@Fiser12
Last active April 13, 2023 08:30
Show Gist options
  • Save Fiser12/fe6d07f89ad1e4cf36e85226f35dcbdb to your computer and use it in GitHub Desktop.
Save Fiser12/fe6d07f89ad1e4cf36e85226f35dcbdb to your computer and use it in GitHub Desktop.
//
// main.swift
// Philosofers problem with actors (monitors)
//
//
import Foundation
let TiempoDeComer: UInt64 = 2_000_000_000
let TiempoDePensar: UInt64 = 1_000_000_000
actor Tenedor {
let id: Int
var filosofo: Filosofo?
init(id: Int) {
self.id = id
}
func tomar(filosofo: Filosofo) async {
guard self.filosofo == nil || self.filosofo === filosofo else {
await Task.yield()
return
}
self.filosofo = filosofo
}
func dejar(filosofo: Filosofo) {
guard filosofo === self.filosofo else { return }
self.filosofo = nil
}
}
class Filosofo {
let nombre: String
let tenedorIzquierdo: Tenedor
let tenedorDerecho: Tenedor
var vecesComido: Int = 0
init(nombre: String, tenedorIzquierdo: Tenedor, tenedorDerecho: Tenedor) {
self.nombre = nombre
self.tenedorIzquierdo = tenedorIzquierdo
self.tenedorDerecho = tenedorDerecho
print("\(nombre) con L\(tenedorIzquierdo.id) R\(tenedorDerecho.id)")
}
func filosofar() async {
while true {
await pensar()
async let tomarTenedorIzquierdo: () = tenedorIzquierdo.tomar(filosofo: self)
async let tomarTenedorDerecho: () = tenedorDerecho.tomar(filosofo: self)
let _ = await (tomarTenedorIzquierdo, tomarTenedorDerecho)
await comer()
let _ = await (tenedorIzquierdo.dejar(filosofo: self), tenedorDerecho.dejar(filosofo: self))
}
}
func pensar() async {
print("\(nombre) está 🧠")
try? await Task.sleep(nanoseconds: TiempoDePensar)
}
func comer() async {
guard
await self.tenedorDerecho.filosofo === self,
await self.tenedorIzquierdo.filosofo === self
else {
return
}
print("\(nombre) está 🍽️")
try? await Task.sleep(nanoseconds: TiempoDeComer)
vecesComido += 1
print("\(nombre) comió por \(vecesComido) vez 🥱")
}
}
let numFilosofos = 5
let tenedores: [Tenedor] = (0..<numFilosofos).map { Tenedor(id: $0) }
var nombresFilosofos = ["Platón", "Aristóteles", "Sócrates", "Epicuro", "Confucio", "Mijail Bakunin", "Nietzsche", "Carl Menger", "Kant", "Descartes", "Hume", "Spinoza", "Sartre", "Seneca", "Epicteto", "Wittgenstein", "Hegel", "Russell", "Heraclito", "Parménides", "Escohotado", "Anaximandro", "Ortega y Gasset", "Jobs", "Anaxágoras", "Zenón de Citio", "Diógenes", "Zenón", "Empédocles", "Plutarco", "Han Feizi", "Lev Tolstói", "Adam Smith", "Agustín de Hipona", "Ludwig von Mises", "John Locke", "Tales", "Pitágoras", "Leibniz", "Bergson", "Musonio Rufo", "Gustavo Bueno", "Schopenhauer", "Marx", "Engels", "Deleuze", "Guattari", "Fichte", "Hobbes", "Averroes", "Locke", "Rousseau", "Tomás de Aquino", "Fukuyama", "Lao Tzu", "Marco Aurelio", "Gottfried Wilhelm Leibniz", "Al-Khwarizmi"].shuffled()
let filosofos = (0..<numFilosofos).map { i in
Filosofo(
nombre: nombresFilosofos[i],
tenedorIzquierdo: tenedores[i],
tenedorDerecho: tenedores[(i+1) % numFilosofos]
)
}
await withTaskGroup(of: Void.self) { group in
for filosofo in filosofos {
group.addTask {
await filosofo.filosofar()
}
}
}
import Foundation
class Filosofo {
let nombre: String
var contador: Int
var tenedorIzquierdo: Tenedor
var tenedorDerecho: Tenedor
init(nombre: String, tenedorIzquierdo: Tenedor, tenedorDerecho: Tenedor) {
self.nombre = nombre
self.contador = 0
self.tenedorIzquierdo = tenedorIzquierdo
self.tenedorDerecho = tenedorDerecho
}
func filosofar() {
print("\(nombre) está 🧠")
tenedorIzquierdo.semaphore.wait()
tenedorDerecho.semaphore.wait()
let eatingTime = UInt32.random(in: 1...3)
print("\(nombre) está 🍽️")
sleep(eatingTime)
contador += 1
tenedorIzquierdo.semaphore.signal()
tenedorDerecho.semaphore.signal()
print("\(nombre) comió por \(contador) vez 🥱")
}
}
class Tenedor {
let id: Int
var semaphore: DispatchSemaphore
init(id: Int) {
self.id = id
self.semaphore = DispatchSemaphore(value: 1)
}
}
let numFilosofos = 5
let tenedores: [Tenedor] = (0..<numFilosofos).map { Tenedor(id: $0) }
let maxFilosofosConTenedor = DispatchSemaphore(value: numFilosofos-1)
var nombresFilosofos = ["Platón", "Aristóteles", "Sócrates", "Epicuro", "Confucio", "Mijail Bakunin", "Nietzsche", "Carl Menger", "Kant", "Descartes", "Hume", "Spinoza", "Sartre", "Seneca", "Epicteto", "Wittgenstein", "Hegel", "Russell", "Heraclito", "Parménides", "Escohotado", "Anaximandro", "Ortega y Gasset", "Jobs", "Anaxágoras", "Zenón de Citio", "Diógenes", "Zenón", "Empédocles", "Plutarco", "Han Feizi", "Lev Tolstói", "Adam Smith", "Agustín de Hipona", "Ludwig von Mises", "John Locke", "Tales", "Pitágoras", "Leibniz", "Bergson", "Musonio Rufo", "Gustavo Bueno", "Schopenhauer", "Marx", "Engels", "Deleuze", "Guattari", "Fichte", "Hobbes", "Averroes", "Locke", "Rousseau", "Tomás de Aquino", "Fukuyama", "Lao Tzu", "Marco Aurelio", "Gottfried Wilhelm Leibniz", "Al-Khwarizmi"].shuffled()
let filosofos = (0..<numFilosofos).map { i in
Filosofo(
nombre: nombresFilosofos[i],
tenedorIzquierdo: tenedores[i],
tenedorDerecho: tenedores[(i+1) % numFilosofos]
)
}
let group = DispatchGroup()
let queue = DispatchQueue(label: "", attributes: .concurrent)
let filofosComiendo = DispatchSemaphore(value: numFilosofos - 1)
for filosofo in filosofos {
group.enter()
queue.async {
while true {
//Es necesario contabilizar cuantos filosofos están comiendo máximo -1, porque sino se generaría un deadlock, uno al menos tiene que esperar
//Se podría arreglar también de otras formas, dando prioridad a otro filosofo o haciendo que un filosofo cogiese el tenedor de la izquierda con la derecha y el de la derecha con la izquierda.
filofosComiendo.wait()
filosofo.filosofar()
filofosComiendo.signal()
}
group.leave()
}
}
group.wait()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment