Asynchronous Programming

Results from an operation may be in some situations delivered to the consumer at some later point than immediately succeeding the invocation of that operation. In such systems the protocol for retrieving and processing these types of results in a software system is AsynchronousProgramming.
Ways to achieve AsynchronousProgramming:

  1. EventQueues.
  2. AsynchronousSystemTrap.


About AsynchronousSystemTrap:

Any OS system call that can complete asynchronously takes a function pointer and context argument pair. When the request completes the OS will call the function and pass it the context. (This is called an AsynchronousSystemTrap on VMS and an AsynchronousProcedureCall? on Windows NT.) It's possible to write entire programs in "continuation passing style" using this mechanism. It's highly efficient, especially for I/O-bound processes.

I though this was called function callbacks.

This was previously discussed in exactly this spot, but got refactored to the above overly-terse summary. That author felt that it was in fact more accurate, after we discussed it, to call it ContinuationPassingStyle than to call it function callback.

Are they really the same? I read that ContinuationPassingStyle never returns from any call, while that's not the case in function callbacks.

[Correct, indeed they are not the same. Full-fledged continuations are more general, and can be used to implement any control construct whatsoever.]

What I really do not like about function callbacks is that you never know when the function callback will kick in (see ThreadsConsideredHarmful), so you are forced to use LockBasedSynchronization for all shared resources, even if you decide not to over abuse threads. The problem with LockBasedSynchronization is: ResourceContention, DeadLock, LiveLock, PriorityInversion, ConvoyFormations. That problem is inexistent when using EventQueues. -- GuillermoSchwarz

ASTs use function callbacks and those can be used to write software in continuation passing style. You know exactly when the function callbacks will be called because the OS defines AST priority levels and gives you methods for enabling and disabling ASTs. It generally works like this:

A startup method disables ASTs, posts some requests to the OS (often I/Os), enables ASTs and terminates. The process stays in a sleep state until one of the requests completes. The AST fires off and the function callback is called. That function callback runs at an elevated priority. It performs some operation on the results of the request, posts other requests and terminates. Each AST is an atomic operation. They are handled in a strictly defined order. There are no separate threads. There is no lock based synchronization.

The ASTs never return values. They handle request completion events and optionally queue other requests.

This isn't the only way to use ASTs, but it is a popular and efficient way.
Regardless of the system in question, we can determine if a queue is used in a straightforward way: if a second and third response come along before the first response has been gotten by the requestor, are they lost? If so, there's no queue. If they're not lost, then they are held in a queue. QED.

I think that's one possible outcome. Another is that subsequent requests block until the first is served. This is typical in Databases when using LockBasedSynchronization (which in the database arena it is called PessimisticLocking). Queues have other problems like for example when it blocks because it is full. -- GuillermoSchwarz

There is a report that there isn't always a queue in DotNetRemoting, though other people could also try it before we could call it scientific. This is asynchronus even though we can't count on the serialization of requests. Calling it "asynchronous" or not depends purely on whether the requestor blocks until a response comes back, not on any other factor.

But can we call this kind of support for asynchronicity a GoodThing? Calling something "a GoodThing" or not depends purely on whether MarthaStewart approves. No, wait. Actually, it depends on a lot of things. Throwing away requests/responses purely because there doesn't happen to be a queue is usually considered a bad thing, because information is destroyed for no good reason. Unless there is a good reason...

As an example, a mouse handler can sometimes ignore events when the system is too busy to draw, if discovering the position of the mouse later is enough to bring the system to a consistent known state. Sometimes, though, losing mouse events would make the system unstable and in need of a boot.

Another example. Historically, originally Unix signals (software interrupts used to signal divide by zero and some other fatal errors, and for some simple minded interprocess communication) had no queue, and suffered RaceConditions as well, which was basically a very bad thing, until their semantics were eventually fixed in BSD Unix and spread to other Unixes from there. It was a nightmare until then.

So it all boils down to whether critical information is permanently lost or not. Same general principles apply anywhere.

And your point being?

Originally there was a paragraph that asked several questions, including whether something or other was "a good thing". I didn't have a point per se, I was answering questions. I don't know why those questions were deleted along the way.


See TcpIp, LockFreeSynchronization, SynchronizationStrategies

EditText of this page (last edited May 6, 2004) or FindPage with title or text search