massive-oss/msignal

Can't serialise Slot => infinite loop

Opened this issue · 8 comments

Hi,
A Signal, and therefore a Solt, is serialisable only when no listener has been added.
If you add a listener you get two issues, at least on flash9 target:

  • the serialiser gets into an infinite loop because of the 'signal' field of Slot. It tries to serialise signal, so it tries to seralise its slots list, so it serialise the first slot, so it serialise the field signal of the slot, which points to the signal itself, so it tries to serialise again the self signal etc.
    Solution: would be to implement custom hxSerialise and hxUnserialise functions for a Slot class to handle signal field differently.
  • on flash9 target: listener field is taken by haxe.Serialiser has a variable and tries to serialise it, but then throw an exception because it can't serialize a function. It's because the field is a $field variable behind getter setter. Getting rid if @isvar don't fix it.
    When i use a serialiser that override serializeClassFields to avoid the serialisation of fields that are Functions, it fixes the issue. i add this line in the loop:
    if (Type.typeof(Reflect.field(v, f)) == TFunction) continue;
    just before
    serializeString(f);
    serialize(Reflect.field(v,f));

I think its more a problem for haxe compiler and Serialiser then mSignal, but you need to fix it to get the first issue of infinit loop that is more a mSignal issue.

Thanks

This should fix the circular reference issue:
http://api.haxe.org/haxe/Serializer.html#USE_CACHE

You probably don't want to serialise added listeners anyway, right?

yes the USE_CACHE set to true fixed the issue. Thanks.
even if it would be still better to have a working behavior by default, and fix the circular reference in the Slot code itself.

"You probably don't want to serialise added listeners anyway, right?"
yes for most of the cases, and in that cases, i don't even want to serialise the Signal at all.
but its better to have it work by default in any case, if people need to serialise it fully. to replicate the exact state of the code for example.

But there's no way you can serialise the listeners anyway, it would be impossible to restore references to the listener closures. Apologies, but this is a rather specific edge case, and given it can be solved in the serialiser adding custom a hxSerialise method seems like overkill (everyone will get that code unless they're using full dce)

Sorry but i don't agree.
It's not a specific edge case, to try to serialize a Signal, which may
have a listener registered (as it is made only for that purpose, its
very likely to have one).
And it is not that specific to try to Serialize a Class instance, that
may have a Signal type member.

It's annoying, because it is a crash of compilation, without clear
error, and hard to find out. If at least it did not crash, but only
don't handle the Unserialize of listeners (with a little explanation in
doc), i think it woud be better already.

I don't understand, why it is overkill to add only one function. Its is
added only once in the Class, not in memory for every instance of it.
But, even with full dce, we need to keep that function, because
Serializer will get it threw Reflect.field call.

Le 29/01/2015 16:18, David Peek a écrit :

But there's no way you can serialise the listeners anyway, it would be
impossible to restore references to the listener closures. Apologies,
but this is a rather specific edge case, and given it can be solved in
the serialiser adding custom a hxSerialise method seems like overkill
(everyone will get that code unless they're using full dce)


Reply to this email directly or view it on GitHub
#14 (comment).

Le 29/01/2015 16:18, David Peek a écrit :

But there's no way you can serialise the listeners anyway, it would be
impossible to restore references to the listener closures. Apologies,
but this is a rather specific edge case, and given it can be solved in
the serialiser adding custom a hxSerialise method seems like overkill
(everyone will get that code unless they're using full dce)


Reply to this email directly or view it on GitHub
#14 (comment).

For your information, about the second issue: Function member listener.
It won't be fixed in haxe.Serializer, because as Nicolas said, it does
not handle variable members with type Function, so it needs to throw a
clear error, and we can't make a specific case for the compiler
generated variable underlying the getter/setter variable, which is
listener in Slot case.
It makes it a second reason, for a custom hxSerialize function for Slot
Class :)

Hey @sebpatu . I wrote an entity system where entities have two signals each, but I don't serialize them intentionally, as all of the observers don't need to be serialized. Do you have a use-case you need help on?