[Vala] Design - Serialization Library - Problem: ref and async



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

Currently, my library client is a turn-based game where the Server
component periodically saves its state if it is modified.

Sincerely,
AmkG


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]