The general idea is that we access Actor.locals from within receive only. As a workaround instead of calling method we send it, so that Actor will call it in appropriate context.
About toImmutable: I think it's a bug that it doesn't work without them.
brianThu 9 Sep 2010
If you are going to share objects between actors, then your objects must be either immutable or serializable. A good example of caching using actors is wisp::WispSession.
sys::Method is immutable (both common sense and docs prove it). We shouldn't even try to serialize it. Just pass reference.
brianThu 9 Sep 2010
The reason you get that error is that your top-level object is not immutable, so it attempts to serialize the list, which in turn contains a non-serializable method object. The actor framework only considers the top-level message object. If it is a list which is not already immutable, then attempts to serialize.
The code which handles this is in Sys.java:
/**
* Make a thread-safe copy of the specified object.
* If it is immutable, then just return it; otherwise
* we make a serialized copy.
*/
public static Object safe(Object obj)
{
if (obj == null) return null;
if (FanObj.isImmutable(obj)) return obj;
Buf buf = new MemBuf(512);
buf.out.writeObj(obj);
buf.flip();
return buf.in.readObj();
}
go4Thu 9 Sep 2010
access Actor.locals by an actor, I learned. Thanks everybody
go4 Thu 9 Sep 2010
My purpose is to put some objects in a pool and share them in appliction. It's like this
using concurrent class Cache{ static const Cache instance:=Cache() [Str:Obj] map:=[:] Obj? get(Str key){ return map[key] } Void put(Str key,Obj obj){ map[key]=obj } Void main(){ instance.put("key","Obj") o:=instance.get("key") echo(o) } }However it's do not allowed to share mutable in fantom. The
Actor.locatscan not achieve my purpose. Someone can tell me how to design it?vkuzkokov Thu 9 Sep 2010
First, the code:
using concurrent const class Cache { static const Cache instance := Cache() private const Actor actor := Actor(ActorPool()) |Obj?[] msg->Obj?| { return (msg[0] as Method).func.callList(msg[1]) } private static Obj? doGet(Str key) { Actor.locals[key] } private static Void doSet(Str key,Obj val) { Actor.locals[key] = val } Obj? get(Str key) { actor.send([#doGet,[key]].toImmutable).get() } Void set(Str key,Obj val) { actor.send([#doSet,[key,val]].toImmutable) } static Void main() { instance.set("key","Obj") echo(instance.get("key")) } }The general idea is that we access
Actor.localsfrom withinreceiveonly. As a workaround instead of calling method we send it, so thatActorwill call it in appropriate context.About
toImmutable: I think it's a bug that it doesn't work without them.brian Thu 9 Sep 2010
If you are going to share objects between actors, then your objects must be either immutable or serializable. A good example of caching using actors is wisp::WispSession.
vkuzkokov Thu 9 Sep 2010
The error itself:
sys::Methodis immutable (both common sense and docs prove it). We shouldn't even try to serialize it. Just pass reference.brian Thu 9 Sep 2010
The reason you get that error is that your top-level object is not immutable, so it attempts to serialize the list, which in turn contains a non-serializable method object. The actor framework only considers the top-level message object. If it is a list which is not already immutable, then attempts to serialize.
The code which handles this is in Sys.java:
/** * Make a thread-safe copy of the specified object. * If it is immutable, then just return it; otherwise * we make a serialized copy. */ public static Object safe(Object obj) { if (obj == null) return null; if (FanObj.isImmutable(obj)) return obj; Buf buf = new MemBuf(512); buf.out.writeObj(obj); buf.flip(); return buf.in.readObj(); }go4 Thu 9 Sep 2010
access
Actor.localsby an actor, I learned. Thanks everybody