Wie halte ich OCaml ab, wenn ich meinen reaktiven Event-Handler sammle?

8

Ich versuche, die OBus -Bibliothek mit Lwt_react . Dies verwendet "funktionale reaktive Programmierung" für Eigenschaften und Signale.

Das Problem (wie in der React-Dokumentation ) beschrieben ist, dass OCaml möglicherweise Ihren Callback während des Sammelns sammelt Du benutzt es immer noch. Es gibt eine keep -Funktion, die den Handler für immer hält, aber das will ich nicht. Ich möchte es schließlich befreien, nur nicht, solange ich es noch brauche.

Also dachte ich, ich würde den Handler an einen Switch anhängen:

%Vor%

Aber mein Event-Handler wird ohnehin müllaufgehoben (was sinnvoll ist, da der Code zum Ausschalten des Switches aufgerufen wird, wenn das Signal ankommt, also ist es nur der Signal-Handler, der den Switch überhaupt am Leben hält).

Hier ist eine vereinfachte (Stand-alone) Version meines Codes:

%Vor%

Ohne die Gc.full_major -Zeile wird normalerweise Done ausgegeben. Damit hängt es einfach bei Waiting for signal... .

Bearbeiten: Ich habe setup (den echten Code) vom Testtreiber geteilt und einen Lwt.protected -Wrapper hinzugefügt, um zu vermeiden, dass das Problem durch die Abstürze von Lwt maskiert wird.

    
Thomas Leonard 14.11.2013, 10:24
quelle

4 Antworten

6

Hier ist ein Ausschnitt aus einem meiner Projekte, der behoben wurde, um dieses Problem mit schwachen Referenzen zu lösen (thx!). Der erste Teil besteht darin, eine globale Wurzel zu behalten, die auf Ihr Objekt zeigt. Der zweite Teil besteht darin, die Lebendigkeit eines Signals / Ereignisses auf das Ausmaß eines LWT-Threads zu begrenzen.

Bitte beachten Sie, dass die reaktive Entität geklont und explizit gestoppt wird, was möglicherweise nicht genau Ihren Erwartungen entspricht.

%Vor%

Lösen Sie Ihr Beispiel damit:

%Vor%     
Def 14.11.2013, 10:57
quelle
1

Hier ist meine aktuelle (Hacky) Problemumgehung. Jeder Handler wird einer globalen Hashtabelle hinzugefügt und dann wieder entfernt, wenn der Schalter ausgeschaltet ist:

%Vor%

Es wird so benutzt:

%Vor%     
Thomas Leonard 14.11.2013 15:07
quelle
1

Ein einfacher Weg, um damit umzugehen, ist, einen Verweis auf Ihr Ereignis zu behalten und React.E.stop aufzurufen, wenn Sie es nicht mehr wollen:

%Vor%     
dim 15.11.2013 09:40
quelle
0

Beachten Sie, dass wenn Sie lwt die Stornierung nicht unterstützt haben, Sie dasselbe Verhalten beobachten würden, indem Sie Lwt.protected (setup ()) durch Lwt.bind (setup ()) Lwt.return ersetzen.

Was du hast, ist:

finished_event --weak--> SETUP --> finished

Dabei ist SETUP ein Zyklus zwischen einem Ereignis und einem Lwt-Thread. Das Entfernen der Lwt.protected just quetscht den letzten Zeiger, damit es tut, was Sie wollen.

Lwt hat nur Vorwärtszeiger (außer, um Abbrechen zu unterstützen), und React hat nur Rückwärtszeiger (die Vorwärts-Zeiger sind schwach). Der Weg, dies richtig zu machen, besteht darin, das Ereignis anstelle des Threads zurückzugeben.

    
dim 18.11.2013 10:41
quelle