Page 1 of 1

Net actor

PostPosted: 02 Sep 2010, 05:36
by nantuko84
Hi!

I've read your blog entry (http://laterna--magica.blogspot.com/201 ... rency.html) about the changes to gui interaction using jetlang concurrency framework. Need to say it was a little bit difficult to understand how all these work together. So please check if I'm right in my understanding of the current workflow (with some questions below):
We create gui and attach GuiMagicActor to every player. Gui has pass button below that publish null into passPriority channel for every actor (one actor for every player) whenever the button is pressed. So every player has its own channels. In game loop the engine gets actions as usual method call ps.getPriorPlayer().getActor().getAction() that subscribes to actions channel, then creates some Actor (ActionActor, ManaActor) that will react to user actions (clicking). Whenever user clicks on some object, if it was subscribed to some channel, it will publish action to actions channel and it will be handled in Parallel class getValue method. this way we separate channels that are connected to gui objects by callbacks and actions channel where game engine get actions from. right?

first of all, why Parallel getValue is synchronized on value object, especially as new istance is created on every call? and why do we need second synchronization in Disposable.onMessage subscribed on fiber (Parallel.getValue.d.onMessage)?

The second question is about Net actor: what is the best way to implement it?
I had working verstion for your previous implementation (with synchronized void putAction), but now I'm in stuck a little. The way the old way worked for me was using State pattern, there was a code like (abstract code)

Code: Select all
// some method handling user clicking on card object
actions = rmi.getActions(card)
action = choose(actions)
rmi.putAction(action)
that put action into NetActor on server and it returned the result in ps.getPriorPlayer().getActor().getAction(). do you have any ideas about the best way of connecting this channels and network stuff. especially I'm confused as your GuiMagicActor now takes Gui as a parameters while previous version (called GuiActor) didn't. and as you understand I have no Gui on server side. please advise. if I explained smth obscurely, I will write it in more details. thank you in advance.

~regards

Re: Net actor

PostPosted: 02 Sep 2010, 10:18
by silly freak
nantuko84 wrote:Hi!

I've read your blog entry (http://laterna--magica.blogspot.com/201 ... rency.html) about the changes to gui interaction using jetlang concurrency framework. Need to say it was a little bit difficult to understand how all these work together. So please check if I'm right in my understanding of the current workflow (with some questions below):
We create gui and attach GuiMagicActor to every player. Gui has pass button below that publish null into passPriority channel for every actor (one actor for every player) whenever the button is pressed. So every player has its own channels.
Right. Note that a Channel doesn't do anything on his own, especially no caching, so if one of the actors doesn't listen, he won't be bothered. This way, since only one actor is active at a time, it's very easy to register multiple actors on the same Gui.

In game loop the engine gets actions as usual method call ps.getPriorPlayer().getActor().getAction() that subscribes to actions channel, then creates some Actor (ActionActor, ManaActor) that will react to user actions (clicking). Whenever user clicks on some object, if it was subscribed to some channel, it will publish action to actions channel and it will be handled in Parallel class getValue method. this way we separate channels that are connected to gui objects by callbacks and actions channel where game engine get actions from. right?
If you meant that the input channels, like players, objects and passPriority, and the output channels, like actions, are separated by the actor's callbacks, you're right. The callbacks handle the input, and the actor in its whole knows how to match that input to an appropriate output.

first of all, why Parallel getValue is synchronized on value object, especially as new istance is created on every call? and why do we need second synchronization in Disposable.onMessage subscribed on fiber (Parallel.getValue.d.onMessage)?
the onMessage method belongs to the Callback and is not executed immediately but in a different thread as soon as a message was posted to the input channel. This multithreaded communication must be synchronized in the classical way: one thread waits for data to get accessible, the other thread notifies it of that data.
The synchronization is not due to possible data corruption, but to enable wait/notify. without it, an IllegalMonitorStateException would be thrown.

The second question is about Net actor: what is the best way to implement it?
I had working version for your previous implementation (with synchronized void putAction), but now I'm in stuck a little. The way the old way worked for me was using State pattern, there was a code like (abstract code)

Code: Select all
// some method handling user clicking on card object
actions = rmi.getActions(card)
action = choose(actions)
rmi.putAction(action)
that put action into NetActor on server and it returned the result in ps.getPriorPlayer().getActor().getAction(). do you have any ideas about the best way of connecting this channels and network stuff. especially I'm confused as your GuiMagicActor now takes Gui as a parameters while previous version (called GuiActor) didn't. and as you understand I have no Gui on server side. please advise. if I explained smth obscurely, I will write it in more details. thank you in advance.

~regards
The Gui class mostly abstracts away some stuff that was previously done in GuiUtil, as static methods, which meant that things were likely to stay around after a game (as we all know from forge^^ it happens now and then).
What I mean by this is that the dependency to the Gui was there before; it was simply hidden through the fact that it was implicitly done by static accesses instead of explicitly through an attribute. I have had a quick look, and the first actor (ActionActor) does not access the Gui object, which may also be a reason that everything was fine for you before.

The main problem is that the Gui is client-only and the Game is server-only, right?
  • The easiest thing as the server would be to delegate all calls on the actor to the client through RMI. For that to work properly, however, you need some info, aka the Game object.
  • The easiest thing as the client would be to re-implement the channels to work remotely, but that has the same problem in that you need the Players and MagicObjects on the client side in the first place.

I have no definitive answer for you, sorry, but a question: how do you handle the gui? LM mentions Players and MagicObjects in the gui, which isn't compatible with client/server. How did you solve that in the past?

Re: Net actor

PostPosted: 03 Sep 2010, 08:32
by nantuko84
I've done with NetActor, it wasn't so difficult as I expected.
I had to create NetMagicActor, NetActionActor, NetManaActor against your GuiMagicActor, ActionActor, ManaActor.
And this is all because of Gui object inside and high coupling between classes (or am I doing smth wrong?). Actually though it works I don't like that the 95% of the code is the same as yours.
may be to create some common interfaces to avoid this?
but anyway it works, and you have only gui, so may be no need to spend your time on it.

Next, as I understand jetland is supposed to hide all synchronization stuff within itself. But you still have to write Parallel class I've asked about before. Is it really ok? Could you please explain once again why this synchronization is needed? And again, when manacost is {1}{G}{G}, you make 3 activateManaAbility calls for every mana. So it means that you need only one reply from the channel for every call, right? if so, have you looked into using AsyncRequest.withOneReply? you may find an example here (#simpleRequestResponse()): http://code.google.com/p/jetlang/source/browse/trunk/src/test/java/org/jetlang/channels/MemoryRequestChannelTest.java

Re: Net actor

PostPosted: 03 Sep 2010, 11:45
by silly freak
nantuko84 wrote:I've done with NetActor, it wasn't so difficult as I expected.
I had to create NetMagicActor, NetActionActor, NetManaActor against your GuiMagicActor, ActionActor, ManaActor.
And this is all because of Gui object inside and high coupling between classes (or am I doing smth wrong?). Actually though it works I don't like that the 95% of the code is the same as yours.
may be to create some common interfaces to avoid this?
but anyway it works, and you have only gui, so may be no need to spend your time on it.
If it works, it's okay for now. I'll look at your approach and see how we can improve the overall situation. The thing is basically that the gui actor does both asynchronous processing and a little gui interaction tacked on, and they can definitely be separated.

That said, it's not going to happen soon, because I really want to release the first alpha version before school starts next week in Austria, and after that my schedule will be a lot different.

Next, as I understand jetland is supposed to hide all synchronization stuff within itself. But you still have to write Parallel class I've asked about before. Is it really ok? Could you please explain once again why this synchronization is needed? And again, when manacost is {1}{G}{G}, you make 3 activateManaAbility calls for every mana. So it means that you need only one reply from the channel for every call, right? if so, have you looked into using AsyncRequest.withOneReply? you may find an example here (#simpleRequestResponse()): http://code.google.com/p/jetlang/source/browse/trunk/src/test/java/org/jetlang/channels/MemoryRequestChannelTest.java
Thanks for the link, I had't found that yet. If I'm understanding it right, it has 2 problems though for my application.

The RequestChannel couples request and response classes, as in the <String, Integer> example. In LM, the request is not so clear, however. Depending on the situation, the inputs are different. If modeled that way, every method in MagicActor would have its own RequestChannel, but that doesn't allow for handling inputs uniformly, e.g. posting clicks on cards to the MagicObject channel.

Second, the result is again processed using a callback, meaning asynchronously. The problem is that Jetlang is more suitable for situations where data is passed from one stage to the next.
Think my downloader: one stage is downloading the file, next is to save to a file. After saving, there is no data to pass on further.
For the actor, you have to get the data back to the same thread, which means to block it until the computation is complete. This is something the actor pattern tries to minimize, but is necessary here.
Ultimately, the Parallel class (or its single method) is something that could be already in Jetlang, but I haven't found it. It's not really part of my application but a utility, so hand-coded synchronization is totally fine for that purpose. The real application code is free of manual synchronization.