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