Function | Package: cg | ToC | DocOverview | CGDoc | RelNotes | FAQ | Index | PermutedIndex
| Allegro CL version 10.1 Unrevised from 10.0 to 10.1. 10.0 version

## post-funcall-in-cg-process

Arguments: function &key arguments (process multiprocessing:*current-process*) type delete-types unless-types

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.

The arguments to post-funcall-in-cg-process are:

- 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.
- process: the value of this keyword argument should be the process that should call the function. It defaults to the current process (the value `*current-process*`). The queued function will later be called only inside the process' main message-handling loop inside the function event-loop; therefore, the process argument should always be a Common Graphics process. (A Common Graphics process should always call event-loop; see About using multiple windowing threads in a Common Graphics application in cgide.htm.)
- 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.)

About design considerations for event-driven applications in cgide.htm for more information.

### 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.)

    (in-package :cg-user)

    (defclass my-win (frame-window)())

    (defmethod mouse-moved ((window my-win) buttons pos)
      (declare (ignore buttons))
      (setq pos (copy-position pos))
      (ide:lisp-message "Mouse now at ~a   ~a"
        (position-x pos)(position-y pos)))

    (defmethod mouse-in ((window my-win) buttons mouse-out-object)
      (declare (ignore buttons))

      (post-funcall-in-cg-process
          (lambda ()
            (format t "~&Moved out of ~a into ~a~%"
              (name-string mouse-out-object)
              (name-string window))
            (sleep 2))
        :type :mouse-in-message)

      #|
      ;; This alternative uses an :arguments argument
      ;; rather than closing over variable bindings.  Note that this
      ;; causes the format arguments to be evaluated when this code
      ;; is posted rather than when it is run later.
      (post-funcall-in-cg-process
          (lambda (format-string &rest format-args)
            (apply #'format t format-string format-args)
            (sleep 2))
        :arguments (list "~&Moved out of ~a into ~a~%"
                         (name-string mouse-out-object)
                         (name-string window))
        :type :mouse-in-message

        ;; Adding this would prune out mouse-in messages that are
        ;; still queued when this later event is handled, so that only
        ;; one mouse-in message will print after the last mouse-in event.
        :delete-types '(:mouse-in-message))
      |#
      )

    (make-window :my-win :class 'my-win)

Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

|  | ToC | DocOverview | CGDoc | RelNotes | FAQ | Index | PermutedIndex
| Allegro CL version 10.1 Unrevised from 10.0 to 10.1. 10.0 version