Fan's static fields has to be a constant. What are the other alternatives to store a global state?
In my case, If I want to store a closure between web requests where should I put it in? Putting it in session does not work because, its not serializable.
brianFri 15 Jan 2010
There is no global state in the traditional sense because that would require synchronization. Instead what you do is use an Actor who manages that state and other actors send it messages to access/change the state.
tacticsFri 15 Jan 2010
If you want to go to bad programmer hell, there's the Unsafe class to bypass the type systems const requirements. But you're better off looking for a more Fantomy solution.
kaushikFri 15 Jan 2010
ok,
But still there is rule that the messages passed to actors should be serializable.. I created the following example to store a closure in an actor against a name and later get it back, can you tell me what's wrong with the code below.. I get the following error sys::IOErr: Not serializable: |sys::Obj->sys::Void|
pool := ActorPool()
closureActor := Actor(pool) |msg|
{
Obj[] lst := (Obj[])msg
//Get the action and see if we are storing or getting a closure
Str action := lst[0]
if(action == "put"){//store a closure
Str name := lst[1] //Type name against which the clsoure should be stored
closure := (|Obj|)lst[2]
closureMap := (Str:|Obj|)Actor.locals.get("closureMap", Str:|Obj|[:])
closureMap[name] = closure
return closure
}
else if(action == "get"){//Get the closure back
Str name := lst[1] //Type name against which we store the closure earlier
closureMap := (Str:|Obj|)Actor.locals.get("closureMap", Str:|Obj|[:])
return closureMap[name]
}
return "Something else"
}
test := |Obj x|{
echo("hello")
}
closureActor.send(Obj["put", "closure1", test])
closure := (|Obj|)closureActor.send(Obj["get", "closure1"]).get
closure(Obj())
brianFri 15 Jan 2010
You can't pass a mutable data structure b/w actors because then that would then expose race conditions.
So what you pass between actors must also be with immutable (const or immutable collection) or serializable.
In your case, functions can be immutable but only if certain rules apply - see Immutable Functions.
KevinKelleyFri 15 Jan 2010
Interesting... I had to try to figure out what you were doing, so I tried your code. First thing that happens is, the closure test you're saving reports itself as immutable, okay, but the list you're passing it in (to the closureActor.send ) doesn't. So, calling toImmutable on that list makes the send happen okay.
Next problem is the map that you're getting from the Actor.locals: you're giving a default, empty map, so since there isn't a closureMap already stored, you get the new empty default one. But you're not saving it back into the Actor.locals, so later (in the "get" response) you just get an empty map again.
Anyway, with those two tweaks, your example works.
kaushik Fri 15 Jan 2010
Fan's static fields has to be a constant. What are the other alternatives to store a global state?
In my case, If I want to store a closure between web requests where should I put it in? Putting it in session does not work because, its not serializable.
brian Fri 15 Jan 2010
There is no global state in the traditional sense because that would require synchronization. Instead what you do is use an Actor who manages that state and other actors send it messages to access/change the state.
tactics Fri 15 Jan 2010
If you want to go to bad programmer hell, there's the Unsafe class to bypass the type systems
const
requirements. But you're better off looking for a more Fantomy solution.kaushik Fri 15 Jan 2010
ok,
But still there is rule that the messages passed to actors should be serializable.. I created the following example to store a closure in an actor against a name and later get it back, can you tell me what's wrong with the code below.. I get the following error sys::IOErr: Not serializable: |sys::Obj->sys::Void|
brian Fri 15 Jan 2010
You can't pass a mutable data structure b/w actors because then that would then expose race conditions.
So what you pass between actors must also be with immutable (const or immutable collection) or serializable.
In your case, functions can be immutable but only if certain rules apply - see Immutable Functions.
KevinKelley Fri 15 Jan 2010
Interesting... I had to try to figure out what you were doing, so I tried your code. First thing that happens is, the closure
test
you're saving reports itself as immutable, okay, but the list you're passing it in (to theclosureActor.send
) doesn't. So, callingtoImmutable
on that list makes the send happen okay.Next problem is the map that you're getting from the Actor.locals: you're giving a default, empty map, so since there isn't a
closureMap
already stored, you get the new empty default one. But you're not saving it back into the Actor.locals, so later (in the "get" response) you just get an empty map again.Anyway, with those two tweaks, your example works.