Sunday, March 30, 2008

Polling or interrupt driven processes

A clever way of procrastinating is to defer to less important tasks only momentarily. For example, you may set your mail application to show a clearly visible sign whenever you have a new email, or get your RSS reader to display a sign when there's a new article for you to read.
In this way, you can use plentiful little unimportant tasks to block those stressful and frustrating tasks that you actually should be performing. By making sure that you're instantly alerted whenever there is an email that might require your immediate attention, and then ensuring that you have a constant stream of emails that could require attention, you will be able to turn what threatens to be productive time into something completely different.

Interrupts are often used in computer system and embedded devices that have to deal with real time demands --- either from other hardware devices, or from big squishy things such as users. Processors, which typically present a serial behavior to the user deal with these annoyances by using interrupts or polling. An interrupt driven machine has hardware dedicated to waking it up in a new state when there's something that has to be done NOW. It will then get on with handling the pesky interruption, and return to the regularly scheduled programming. Unless, of course, another interrupt happens while the interrupt is being handled. This can put the machine into a terrible state of confusion, so a common approach is to simply not allow it. Another is to allow it, but only allow more important things to interrupt, for example using interrupt priority levels. When servicing a level 1 interrupt, you might be interrupted by just about anything, whereas you would never get interrupt when running, say, a level 31 interrupt. This would be equivalent to not letting a coworker interrupt your work, but immediately responding to your manager.

Computers that don't have interrupts use polling; instead of performing useful work, they check on the state of the things that could be sending an interrupt. (Has the user pressed a key? No? What about now? No? What about now? No? ...) While interrupts superficially appear useful for the purposes of procrastination, polling is pure brilliance. By training yourself to go your email application and check for new email every so often (and then go to CNN, just in case the world is about to end, or O.J. got up to something, and then check FARK, because if O.J. didn't get up to anything, surely someone did, and ...) there is really no end to how much procrastination you can get in. Further, though it is probably already obvious to the astute reader, it turns out that interrupts are only truly useful if they force you to poll; a good email filter would trivially sort out the wheat from the chaff and leave you without good interruptions. Polling, on the other hand, because it forces you to actively check, and ideally to remember a lot of external state (have I already read this story?) will not only take time in its own right, it will also have the added benefit of significantly decreasing your productivity when you do happen to turn to the real task. 

Home work for the next time:
Read this blog every minute for the next several days, just in case I edited the article.
If you're not able to do that just yet, don't give up, try practicing on fark.com first.



Saturday, March 29, 2008

Lazy invocation

Closely related to procrastination is the deferral of work. Unlike procrastination, this does not guarantee the replacement of one useful activity by some other less important (but less stressful or strenuous) activity. Instead, the idea (absurd, surely!) is to defer the less important work, and perform it later, or perhaps not at all. 

Lazy languages take this to one extreme, and guarantee that it will be impossible to observe them doing any work that they do not have to do. Of course, programs then spend more work figuring out what they have to do than actually performing the work, but that is just part and parcel of being truly lazy. As it turns out, compilers for these lazy languages spend lots of time working out when it is possible to not be lazy --- sometimes the programmer has to help out with strictness annotations --- and some even go so far as to be eager, assuming that you might need something in the future, and that they might as well just get it out of the way!

In a more productive case, the work is performed asynchronously, perhaps incrementally, or even by someone else, and if we're so fortunate that it has already been done by the time we need it --- surely in some distant, and unlikely future --- we have to do nothing other than reap the benefits. If not, we have to wait, or even complete the task ourselves. These asynchronous units of work that we hope not to have to do ourselves are often called futures.

sort(array, count) {
if (count > 1)
half = count / 2;
left=future(sort(array, half));
right=sort(array+half, count-half);
return merge(need(left), right, count);
}
return array;
}

(A really clever compiler for a lazy language might be able to figure out that  it could introduce the future above, taking that burden away from the programmer. Writing one of those appears to be hard work.)

A procrastinating version of the program above might look something like this:

sort(array, count) {
if (count > 1)
half = count / 2;
left=future(sort(array, half));
right=future(sort(array+half, count-half));
while(!(done(left) && done(right))) clean_room(); 
result= future(merge(need(left), need(right), count));
while(!done(result)) pot_plants();
return need(result);
}
return array;
}