Le samedi 02 avril 2016 à 21:08 +0800, Alan Manuel Gloria a écrit :
Hi all, I'm trying to design a serialization library for Vala. My initial design sketch was something like this: // Library /* An object that can be saved or loaded. */ public interface Serializable : Object { public abstract async void serialize(Archive ar) throws Error; } /* An object that can save or load. */ public abstract class Archive : Object { public abstract bool is_saving(); public abstract async void archive_string(ref string s) throws Error; public abstract async void archive_int(ref int i) throws Error; /* .. a dozen other methods for various types .... */ } //Client code internal class Something : Object, Serializable { private string name; private int id; public virtual async void serialize(Archive ar) throws Error { yield ar.archive_string(ref name); yield ar.archive_int(ref id); } } The point of the design is that a Serializable would, ideally, have a single section of code for both loading and saving, to ensure that loading and saving are correctly compatible. This pattern is similar to some serialization libraries in C++. Since an archive could either be saving or loading, it needs ref access. Unfortunately, it seems that there are a few good reasons that async and ref are not compatible. The major one seems to be that exposing a ref argument of an async method to a non-async method could lead to a bug where the non-async method uses a local variable and passes it into the non-async method. (for an async method, local variables are actually allocated in its data structure, so it's safe to use a local variable in an async method to another async method by ref). I'd like to ask that ref and out be allowed in async, and restrict them so that async methods with ref/out arguments can only be called from other async methods (to avoid non-async variable reffed by an async method problem), but I'd probably need to work on that myself, haha. So, given the limits of today's Vala, what would be better? 1. Remove "async". This limits me to total data sizes that can comfortably be written or saved while blocking the main loop. I could also serialize in a true OS background thread, and ensure somehow that the object being serialized is completely locked until the entire serialization is completed. +: retain similar style as above. -: blocking. 2. Remove "ref". That means I code something like: public virtual async void serialize(Archive ar) throws Error { name = yield ar.archive_string(name); id = yield ar.archive_int(id); } +: still nonblocking. -: specify object field twice (violate DRY), mismatch may lead to subtle bugs
Use out parameters instead, they are known to work with async functions. Personally, I would suggest that you use GVariant for serialization. APIs are here: http://valadoc.org/#!api=glib-2.0/GLib.Variant There is an example here using VariantBuilder and VariantIter http://va ladoc.org/#!api=glib-2.0/GLib.VariantIter Basically, an async method in Vala is a GSimpleAsyncResult that run in a background thread (see GIO thread pool), so you don't really need to work with threads here. You could use Redis to save the states as it support binary storage or store them in files.
Currently, my library client is a turn-based game where the Server component periodically saves its state if it is modified. Sincerely, AmkG _______________________________________________ vala-list mailing list vala-list gnome org https://mail.gnome.org/mailman/listinfo/vala-list
-- Guillaume Poirier-Morency <guillaumepoiriermorency gmail com> Étudiant au baccalauréat en Informatique à l'Université de Montréal Développeur d'application web Mon blog: https://arteymix.github.io/ Mon projet de coopérative: https://pittoresque.github.io/ Clé PGP: B1AD6EA5
Attachment:
signature.asc
Description: This is a digitally signed message part