Last active
April 13, 2023 08:30
-
-
Save Fiser12/fe6d07f89ad1e4cf36e85226f35dcbdb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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