View Single Post
Old 11-16-2012, 02:33 PM   #8
camlorn
Member
 
Join Date: Aug 2011
Posts: 144
camlorn is on a distinguished road
Re: Event-based with threads instead of game loop

Going to try to clarify a bit. The edited part could probably be clearer, but for some reason firefox crashed twice before I could post it, I had to move to internet explorer, and by that point I was too frustrated.

Anyhow, it's like this. I, the mud newbie, want to start a mud, yay me, so I go download your codebase (this happens a lot, look around the forums). I don't know much about programming, and I want to add a new whatever, command, spell, doesn't much matter. So I go look at how to do it and the first thing I see is this thing called a thread, which I've never heard of. So I go try to add a command, but I can't debug, and I don't know what I'm doing, and I'll probably end up throwing out your codebase. My point was that an executor thread makes this more feasible, but only if the fact that things are running on an executor thread is hidden. If you are going to be the only programmer, and don't want to try for more general adoption, it's not such a big deal. Writing mob scripts could or couldn't become interesting, I really don't know.

Akka is something I don't fully understand; let me start off by admitting that. I understand what it does, just not how to use it. But here's a quick explanation of the idea behind an actor as I understand it, and why it may (or may not) work.

On a cpu, I have 4 cores. This means that for "true" multitasking--tasks running literally at the same time and without time sharing by the OS--I can have 4 threads. I can have more than that, if some or most of my threads are sleeping, but I can't have more running, or two of my threads are going to share a core. This means that my code needs to figure out how many cores are available and determine the best running case. In a mud, given that it really doesn't use that much, you can probably just deal with the time loss.

Actors say, do away with everything is a thread. Instead, everything is an actor and may receive a message. You can have an actor that takes up an entire thread and sends messages to the others--by my understanding this is a common approach--sending messages like "tick" or whatever. I then write my actors more like state machines (not really, but it helps to think about it like that, in a way). Each message will wake up my actor, cause it to do something. If I want a message back, I can wait for a reply, or more commonly, I can go do something else and check for a reply when I need it later. There are no such things as locks or race conditions: instead, you have an actor that is in charge of a resource, and only that actor can get at that resource, and if I want something from that resource I send a message to that actor and wait for a reply. My actor blocks the thread that it's on until it stops executing, at which time another actor gets put on that thread behind it. The trick here is to make actors that don't block, i.e. wait for 5 seconds before returning.

To implement something like a delay, every time I get the tick message, I decrement a counter; when that counter gets to 0, I do whatever I was delaying to do. In languages like scala with closures and such, it's actually possible to do a lot of neet tricks here: inherit from the generic wait actor, for example, and set a variable to the function I want to call. Scala makes this simple and easy: typically, actor ! message(parameters), but scala isn't exactly trivial to understand, so I'd not switch just for a convenient syntax.

So, how do you make it deterministic. Well, each actor has a mailbox, and akka provides a variety of types: I can have priority mailboxes where every message is prioritized, I can have queue mailboxes, there's a whole bunch of options. So long as all my actors aren't running at once, I can have hundreds of thousands, and the akka system will handle determining which ones need to run on what threads. I just bind my game-controller actor to a thread all its own, and let it send messages like tick and regen or whatever to all the others (you can have actors register that they are interested in a message if you want to make it more efficient, and want to prevent waking up 100000 at a time). I don't know if this is deterministic enough, but in a language like scala at least, it looks almost like method calls, and you can just say that a command can never wait unless it uses the trick you outline somewhere in your documentation.

And, this doesn't much matter, but akka does a lot more. If I code it correctly, i.e. everything is an actor, and if I want to look up something about or change a room I send a message to the actor representing the room instead of having a room class, I can then make it such that my mud runs across multiple computers. Akka handles all the serialization and such, and so long as I'm careful to make everything an actor instead of a class, I get simple inter-computer calls (well, kind of. you do have to deal with some stuff--i.e. one of the computers being turned off). There probably isn't much point, not for a mud, but I do have an idea that it might be useable somehow to make some sort of multi-mud where everyone hosts their own areas, or something. I am nowhere near smart enough to actually design that, though.

To me, actors are what you want here. But, to me, using a simple game loop is more what you want here, and I do have to say that I'm going to stand by that.

Time to go look up the dragon's dinner problem.
camlorn is offline   Reply With Quote