Wenn ich so weiter drüber nachdenke - bei neuen Tasks musst Du mit Polymorphie die Queueverarbeitung nicht ändern. Deine Implementierung ist also nicht sOlid. Man kann von deiner MVar nicht erben, wenn man neue Tasks braucht. Da ist schon die Task-Enumeration falsch, das müsste eigentlich ein Interface sein.
Ja, damit hast du mich überzeugt. Ich werde das in den nächsten Tagen mal so implementieren. Wenn du möchtest, kann ich dich gerne als Contributor im Repo verlinken. Dein Code-Review ist wirklich enorm hilfreich.
Man musste aber definitiv die swap-Aufrufe in die Receiver einbauen, sonst ist nichts passiert. Ich lag also falsch. Wenn die taskQueue leer ist, ist sie leer.
Okay, dann ist das kein Bug, sondern works as intended. Das ist ein Fehlgebrauch der Library. Die Endlos-Rekursion steckt ja nicht im Library-Code, sondern im Anwendungs-Code. Imho. sollte es dazu nicht kommen, wenn der innere swap-Aufruf asynchron stattfindet, das werde ich nochmal testen.
Dann hab ich noch was gespielt:
var x = MVar.newEmpty<string>(); x.swap("bar").then(data => receiveData("bar", data)); x.swap("hon").then(data => receiveData("hon", data)); x.take().then(data => receiveData("tk1", data)); x.take().then(data => receiveData("tk2", data)); x.take().then(data => receiveData("tk3", data)); console.log("pushing data"); x.put("foo"); x.put("moo"); x.put("boo"); x.put("zoo"); function receiveData(at: string, w: string) { console.log("receive at " + at + " / got " + w) }
Welche Ausgabe sagst Du voraus?
Vorhergesagt, habe ich folgendes, aber auch weil ich meine Implementierung kenne:
pushing data
receive at bar / got foo
receive at hon / got bar
receive at tk1 / got hon
receive at tk2 / got moo
receive at tk3 / got boo
Du hast vielleicht folgendes erwartet:
pushing data
receive at bar / got foo
receive at hon / got moo
receive at tk1 / got boo
receive at tk2 / got zoo
receive at tk3 / got bar
Das wäre die Ausgabe, wenn man swap
durch take
und put
ersetzt:
x.take().then(data => { receiveData("bar", data); x.put("bar"); })
x.take().then(data => { receiveData("hon", data); x.put("hon"); })
x.take().then(data => receiveData("tk1", data));
x.take().then(data => receiveData("tk2", data));
x.take().then(data => receiveData("tk3", data));
Beides macht irgendwie Sinn. Die erste Variante arbeitet streng nach dem FIFO-Prinzip. Die zweite Variante würde take
und put
in eine Beziehung zu swap
setzen. Ich glaube, der zweite Fall wäre tatsächlich schöner. Ich muss mir nochmal anschauen, was Haskell da macht.