Sign in to follow this  

More Stackless Python Learning Troubles

This topic is 3293 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I have learned one thing: Stackless Python is pretty sweet! I've had a lot of fun using (abusing?) it to make programs in an object-oriented manner, without making any classes. I quite enjoyed having my objects really be functions. Whether that's useful or idiomatic is another question entirely, but it was refreshing, for some reason. That said, I'm still struggling some ways. To illustrate my troubles, I'll introduce you to the "game" I'm practicing my stackless skillz with. Basically, there are a bunch of bombs placed on the screen. If the user clicks on a bomb, it explodes and then sets off any bombs near it. Simple, right? Well, there's one thing bugging me. I have an actors list, which stores the channels of all actors. There's a World() function, which sends out "WORLDUPDATE" messages every 0.03 seconds to every actor. Then it sends a blank message to the Graphicsfunction, which wakes that up and renders the scene. The problem comes in when a chain reaction is set off from a bomb exploding. One bomb gets a "BUTTONDOWN" message, explodes, removes itself from the actors list, then sends off an "EXPLOSION" message to all actors in actors. Those then get the "EXPLOSION" message, explode, remove themselves from the actors list, send off their own "EXPLOSION" messages. The issue is that actors receive the "EXPLODE" message sometimes only after the next frame has begun. While this isn't strictly a problem in my program, I could see this running into issues later on. I can imagine messages being received in the wrong order, or at the very least there being a one-frame delay between events and their responses.
Another thought. My instinct with Stackless seems to differ from this article. If I have an actor receiving two types of events, I would probably put their two events in separate channels, being read in separate tasklets. This article, it would seem, would give the actor one channel and then send both messages, with some identifier as to what type the message is, to the same channel. What do you all think of these two methods?

Share this post


Link to post
Share on other sites
Quote:
Original post by Ezbez

Well, there's one thing bugging me. I have an actors list, which stores the channels of all actors. There's a World() function, which sends out "WORLDUPDATE" messages every 0.03 seconds to every actor. Then it sends a blank message to the Graphicsfunction, which wakes that up and renders the scene.


That's the canonical game loop. It doesn't work well with event driven design.

You don't send any "UPDATE" messages, unless that entity does need periodic update. Your input generates click event. You send "CLICK" message to bomb. That one sends "I EXPLODED" message to neighbors. And so on...

The question is, when to render.

One way is to send "I NEED RENDERING" message to Renderer whenever an entity changes. Renderer checks when it rendered something last, and if difference between last and current time is > X, then it renders the scene.

Quote:
While this isn't strictly a problem in my program, I could see this running into issues later on. I can imagine messages being received in the wrong order, or at the very least there being a one-frame delay between events and their responses.


There are no frames, messages drive the simulation. To explicitly determine when a frame is done, actors need to signal they are done with current frame (see below).

The problem with message ordering also exists, but is not trivially solvable. From what I can tell, the only automated solution is to actually check how messages and changes are propagated, then use topological sorting to execute them in proper sequence - but that's not trivial nor viable in this particular case. Just run tests is likely most productive at this point.

Either way, there is no definitive solution to this problem, people are still working on it.

Quote:
Another thought. My instinct with Stackless seems to differ from this article. If I have an actor receiving two types of events, I would probably put their two events in separate channels, being read in separate tasklets. This article, it would seem, would give the actor one channel and then send both messages, with some identifier as to what type the message is, to the same channel. What do you all think of these two methods?


If you use two channels, you can use that to effectively control frames (you don't need them for types).

Have each actor read from channel 1. Any messages it sends to other actors are sent to their channel 2. When empty, it sends message to world "I AM DONE".

When world knows all actors are done, it runs the renderer. Then, channels are swapped. All read from 2 and write to 1.

The only tricky part remains how to know when all actors are done. One way is that after each frame, you send "LAST MESSAGE" to all actors. Since current read channel has been filled in previous frame, this will really be the last message they will receive in current frame.

Simulation will now run as fast as possible, but intra-actor communication will take one frame. Despite convenience, this type of simulation is better achieved without automatic scheduling, since it allows more control over certain aspects. For example, in above case, no more than one generation of bombs can explode per frame.

Share this post


Link to post
Share on other sites
Thanks for the reply.

I've decided to make all gameplay messages independent of frames. In other words, I'm going to use the simplest solution (just doing it) unless something really problematic arises.

One more question, though.

Let's say I have an actor which needs to tell all other actors around it of something. If it has a list of actor's channels around it, it can go like so:

for a in actors:
a.send( message )

But, since each channel.send() reschedules the tasklet to the end of the queue (at least, that's how I understand it), it won't be able to send off all those signals in any timely fashion. If I also put a tasklet that drew the frame whenever it came up, then I would think that actors could only send one message per frame, since any send() would send them to the back, behind the drawing task.


The only solution I have thought of is to pass the list of actors that need the message passed to in the message. Then the first receiver would do his stuff, then send off the message again to the next one in the list. Continue until complete. But, this requires that the receiving actor knows the wishes of the original actor, and if the actors list was badly ordered (reverse of how they are on the queue), it could still take one frame per message.

What would you do?

Share this post


Link to post
Share on other sites
I would stop treating channels as a message-passing mechanism, that's what.

Yes, I know that sounds counter-intuitive.

But really, channels are there as process scheduling systems. Yes, they are designed to carry useful semantic payloads, but that is secondary to the way in which they exist to regulate cooperative multitasking. If you just want to pass information about, or broadcast it, there are simpler ways. One of the benefits of Stackless is that it the cooperative multitasking means you can treat any operation as atomic. So you could happily push messages into another actor's 'inbox' or whatever, knowing there's absolutely no risk of that actor prematurely or dangerously accessing that inbox until your current tasklet stops running.

Share this post


Link to post
Share on other sites
That's a good point, Kylotan.

I can't say I'm really impressed with that "Concurrent Programming with Stakless Python" article. Pretty much everything it has taught, beyond basic syntax and library useage, seems to be less than helpful. Maybe I'm just misunderstanding it. Too bad it's nearly the only thing out there for Stackless Python.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ezbez

Maybe I'm just misunderstanding it. Too bad it's nearly the only thing out there for Stackless Python.


The robots example isn't best, since typically you don't want this type of concurrency.

In most cases, "robots" would be systems. Physics, logic, networking, ... that would take care of their own aspect, but over all data. So physics would update location and motion, logic would decide upon actions, and they would pass data related to that.

Example shown with robots is valid, but in practice tends to result in a lot of overhead and too convoluted logic once you need to entities to interact.

The robots tutorial is actually an example of important problem it doesn't solve, namely collision detection, which is handled in one single place, and might be biggest bottle-neck, so all concurrency doesn't help if that one is holding everyone back (problem in multi-core or distributed computing).

Primary benefit of stack-less python and its alternatives is responsiveness. Same approach, but different implementation is desirable in scalable concurrent (multi-core) settings, where data sharing should be minimal, and systems run in isolation.

But the real problem with this type of design is how to partition the problem domain into such isolated, yet efficiently cooperating pieces. That's not something a tutorial can teach, and not even always possible.

Share this post


Link to post
Share on other sites

This topic is 3293 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this