post-funcall-in-cg-process

This function places a funcallable object to be called later onto a
"funcall queue" for the specified Common Graphics process. The
function call will be made only after all pending window messages in
that process have been handled completely, and after all function
calls that were already in the funcall queue for that process have
been called and have returned.

The queued funcalls are called only by the main event-handling loop
inside the function event-loop, which is normally called by any Common Graphics
process. While calls to functions such as process-wait or process-pending-events will handle
window messages at that time, these calls will not process queued
funcalls.

This function is typically useful when message-handling code calls
certain functions that block, which allows further messages to be
handled while the code that is running for the current message is
blocking. If further messages arrive during the blocking period, this
can cause message-handling code to be re-entered or otherwise run in
an order that is not expected, which may cause the application to get
into a confused or hung state.

In particular, calls to process-wait, with-process-lock, sleep, or process-pending-events will cause
subsequent messages to be handled immediately (or when they occur
during the function's waiting period). Note that various Common
Graphics or other Allegro CL functions may call these functions
internally, and therefore will have the same potential problem; for
example, the AllegroStore macro with-transaction calls with-process-lock, and so
Common Graphics message-handling code that calls
with-transaction may want to queue this call if it might cause
confusion when intervening messages all wait on the lock while the
same process is already using it.

function must be a funcallable object (a function
name or function object). The function will be called later when the
posted funcalls are processed. The function will be passed the
arguments that are in the list passed as the
arguments argument, if any.

arguments: the value of this keyword argument
should be a list of arguments to pass to
function. An alternative to passing an argument
list here is to pass the function argument as a
closure that takes no arguments but instead closes over any variables
that need to be passed. A closure form may be more elegant, but note
that the closed-over variables will be evaluated later when the
function is called, rather than when it is posted. Passing an
argument list instead will evaluate the forms that produce the
arguments at posting time.

type: the value of this keyword argument, if it
is specified, should be an arbitrary symbol to classify this queued
funcall. For example, if you are showing a message when the mouse
enters a widget, you might want to pass
:mouse-in-message to indicate that this is a queued
funcall for a mouse-in message. This value may be used by subsequent
queued funcalls that specify delete-types or
unless-types arguments. (This argument is not
otherwise used.)

delete-types: the value of this keyword argument,
if it is specified, should be a list of symbols that may have been
passed as the value of the type argument to
earlier calls. Any currently queued funcalls of those types will be
deleted from the queue when this function call is placed there. As an
example, if you are now showing a status-bar message when the mouse
enters a widget, for efficiency you may want to remove any currently
queued funcalls for status-bar messages, since they would get
overwritten immediately anyway.

unless-types: the value of this keyword argument,
if it is specified, should be a list of symbols that may have been
passed as the value of the type argument to
earlier calls. If there are any currently queued funcalls of any of
those types, then this funcall will not be added to the queue. This
could be useful for determining that a currently queued call is
already going to handle whatever this funcall was going to handle, and
so there is no need to queue this one in addition.

Note that the queued functions are always called asynchronously, and
so the caller of post-funcall-in-cg-process cannot
wait for a returned value or an indication that the code has run. So
it is probably most useful to call post-funcall-in-cg-process at the
very top of a message-handling method or function, so that everything
that would have been done by the event-handler is done instead by the
queued function call. (eval-in-listener-thread, on the
other hand, can wait for completion, though it may be used only in the
IDE and not in a standalone application.)

An Example

Below is an example that causes each mouse-in event of a window to
print a string to the Debug Window (when the example is run in the
IDE) and then to wait two seconds. Because this action is queued by
calling post-funcall-in-cg-process each
time, the messages will not print more often then every two seconds,
even if you rapidly move the mouse into and out of the window, because
each queued function will be called only after the preceding one has
returned. (Without the call to post-funcall-in-cg-process, the
call to sleep
would cause further messages to be handled, and each string would be
printed almost immediately when the event occurs.)

Notice that the mouse-moved method continues to
print coordinates immediately to the IDE status-bar, even as the
printing done by the mouse-in method is delayed by the
calls to sleep. (In real
application code, the delay would more likely be done by a call to
process-wait or
with-process-lock
rather than a call to sleep
like the one in this simple example.)