Thursday, September 14, 2006

Implicit pausing MiniAxon

Consider a version of Axon where microprocesses pause by default after each iteration of main. Such a setup encourages the writing of efficient components by making polling difficult (but not impossible - a clock/tick threadedcomponent could send a wakeup message every second). This removes the ideas of pausing and unpausing - activate() can be used instead of unpause().

I also have different ideas about trigging the activation/unpausing of components. The component should be able to specify events that wake it. For inboxes, the receipt of a message could wake the parent component, or not. For outboxes, the removal of a sent message from the recipient inbox (through recv()) could also wake the parent.

There are occasions when you would not want delivery to an inbox to wake the component:
Consider this component:
class Combiner(component):
Inboxes = ["a", "b"]

def __main__(self):
while 1:
while self.dataReady("a") and self.dataReady("b"):
newmsg = [self.recv("a"), self.recv("b")]
self.send(newmsg, "outbox")
yield 1
It waits until both inbox A and inbox B have at contain one message each, takes the first (oldest) message from each, combines them into a two-element list and sends that list on.
If A contains messages, but B contains none, the Combiner is waiting for B. The addition
of messages to A does not merit waking the component - it won't be able to do anything more than it could do before.

Syntax such as:
self.wakeOn("b")
could be used to accomplish this selectiveness.

1 Comments:

Blogger Michael said...

Hi Ryan,

Regarding the idea of components that pause by default - it's an interesting idea, and one that could happen. My suggestion would be, as usual, rather than argue the case of being better or worse to simply try it :-)

After all, we do already have generator components and threaded components, having an "always pause component" would be interesting. It would certainly make some classes of component easier, and I can see it wouldn't work for other classes of component.

Regarding triggering pause/unpause, again, it's worth noting that components don't actually have a pause method at all - that actually happens only in the microprocess level. Having criterion for waking up is a good thing. Some of the aspects of Kamaelia are based on the Amiga's "intuition" subsystem (this is clearer in the pygame event handling for the same reasons) but one part not handled yet is a way of dealing with pausing and unpausing with detailed criteria.

We've played around with this, but I suspect there's more playing to be done before we find what is the really useful approach.

The current scheme for unpausing a component is at best, coarse (but useful). One thing that is worth bearing in mind in all this is that the API for pausing in Kamaelia is not based around making things hard for the user, but easier. (Making things baroq is easy, making it simple is hard)

This doesn't preclude alternate base classes, nor should it dissuade you from playing with ideas.

Also, the pygame code is littered with a variety of ideas, which at some point need to be consolidated. One of these is precisely the approach you said (not quite same description):

self.waitBox("callback")

(note that implementation there is not designed for low CPU usage because it's aim is to wait for data, not to risk a deadlock scenario. (more places you pause, the greater the risk of deadlock)

Also another experiment is with a WaitComplete syntax, which does some interesting things. Eg:

yield WaitComplete(
self.requestDisplay(DISPLAYREQUEST=True,
callback = (self,"control"),
size = (self.render_area.width, self.render_area.height),
position = self.position
)
)

6:59 PM  

Post a Comment

<< Home