APC
Asynchronous Procedure Call is a
synchronization mechanism that works somewhat differently from the common and
simpler synchronization objects.
We use the basic synchronization objects such as a MUTEX in
our thread to signal another thread that it should stop execution and wait until
our thread is done with its work. APCs use a different strategy and thus may
require a different design for the application. An APC is a type of callback
function that we can call. In a way it is similar to using a regular function
pointer and calling it. We would call such a function when we need to notify
another Task about something. This Task will then handle the event inside the
callback function so that instead of waiting on an event and then working after
the event is signaled, the actual work is coded in the callback function. The
problem with a regular callback function is that it is called under the context
of the caller, so for example when thread A is calling the callback then the
callback is running under the context of thread A and thread B is probably doing
something else in parallel. Think about a thread that is repainting a window
when another thread has some new information to draw on that window.
The mechanism of APC is here to solve this synchronization
problem without protecting resources with a MUTEX and without using an Event for
signaling. When we use an APC our thread is telling the operating system to make
the other thread call the callback function under its own context. In other word
Task A is telling Task B to execute a function. Task B will not interrupt its
work to perform this action. Instead it will finish all the things that it
started with and then when it is done it will begin the execution of the
callback function. This is synchronous because it is assumed that the callback
function is called only after the Task has completed anything that it was doing
and so it has finished using any resources. If we take a look at the example of
a window then the task that is painting the window will finish painting the
entire window and only then it will begin updating to the new data.
The mechanism of APC will wait for the target Task to finish
all of its work. Since applications today are idle most of the times, waiting
for the next system event to respond to, it is assumed that when the Task is
finished with all of its work then it will enter a wait until the next system
even t comes. The operating system (or synchronization library) will steal the
Task when it is in a wait state and make it jump to the address of the callback
function. When the function returns then the Task goes back to continue the wait
state on the original code and function.
Using this synchronization mechanism requires that we do
not wait during an operation so we do not use a MUTEX or an Event when we
are dealing with a resource.
This is OK:
-
bool MyFunc( )
-
{
-
Wait for MUTEX A
-
-
Wait for MUTEX B
-
Use resource A
-
Use resource B
-
Use resource A
-
Release MUTEX B
-
-
Release MUTEX A
-
}
The following is not:
-
bool MyFunc( )
-
{
-
Wait for MUTEX A
-
Use resource A
-
-
Wait for MUTEX B
-
Use resource B
-
Use resource A
-
Release MUTEX B
-
-
Release MUTEX A
-
}
Our design has to be aware of the existence of APCs and we
should not use the Wait API during the work with a shared resource.
The advantage in using the APC mechanism is obvious: We don't
need to synchronize access to our resources. The performance of the application
increases and the complexity for the programmer decreases. This is one of the
really few cases where there is no tradeoff between code manageability and
runtime performance.
A special feature that can be implemented using an APC for a
system that does make extensive use of simple synchronization mechanisms is that
the APC mechanism allows us to externally instruct the Task to run code when it
is in a Wait State. In other words even though the Task is still waiting we can
order it to do something. By using an APC we can write a Watchdog mechanism that
can help the Task recover from a Deadlock as gracefully as possible, saving
data, checking statuses, closing open files, devices and Handles, and performing
some cleanup. This is better than the alternative which is most times just keep
the Task running or terminate the Task without knowing what had happened to it.
In Kernel and Real-time operating systems an APC is used to
complete a task that has several stages. Such tasks usually start on a high
priority and have some additional processing to be done that can happen under
lower priority. This is not the same kind of APC that applications in User Mode
use.
More on
Microsoft's
MSDN
No information
on Wikipedia