%eclent; ]> Multithreading
Multithreading Reference mp:all-processes Return the list of active processes. Function mp:all-processes Description Returns the list of processes associated to running tasks. The list is a fresh new one and can be destructively modified. However, it may happen that the output list is not up to date, because some of the tasks has expired before this copy is returned. mp:exit-process Exit the task from which it is invoked. Function mp:exit-process Description When called from a running task, this function immediately causes the task to finish. When invoked from the main thread, it is equivalent to invoking with exit code 0. Example See . mp:holding-lock-p Determine whether current process holds the lock. Function mp:holding-lock-p lock lock An object of type mp:lock. Description Returns true if the current process holds the lock. mp:interrupt-process Interrupt a task. Function mp:interrupt-process process function process An object of type mp:process. function A function, which is to be executed in the interrupted process. Description This function sends a signal to a running task. When the task is free to process that signal, it will stop whatever it is doing and execute the given function. Example Kill a task that is doing nothing (See ). (flet ((task-to-be-killed () (loop (sleep 1)) ; Infinite loop )) (let ((task (mp:process-run-function 'background #'task-to-be-killed))) (sleep 10) (mp:interrupt-process task 'mp:exit-process))) mp:get-lock Try to obtain a lock. Function mp:get-lock lock &optional; wait lock An object of type mp:lock. wait Whether to wait to obtain the lock. Defaults to &nil;. Description This function tries to obtain exclusive use of a lock. If wait is &t;, and another task owns the lock, it may wait until the lock has been released. If wait is &nil; it will return true if and only if it succeeded on acquiring the lock. Example See . mp:giveup-lock Release a lock we have obtained before. Function mp:giveup-lock lock lock An object of type mp:lock. Description This function releases a lock which had been previously obtained using . Example See . mp:make-lock Create a new lock. Function mp:make-lock &key; name name A symbol to name the lock. Names not be unique. It defaults to &nil;. Description This function creates a lock object that can be use to synchronize different tasks. The own is initally free and not owned by any task. Locks are typically implemented using Posix mutexes. When garbage collected, a lock is automatically freed. Example See . mp:make-process Create a new thread. Function mp:make-process &key; name initial-bindings name A symbol to name the process. Processes can be unnamed and names need not be unique. initial-bindings The list of special variables which will be local to the new process. It defaults to &t;, which means copying all variables which are local to this process. Description This function creates a separate task, with a name, set of variable bindings and no function to run. See also . Example See mp:process-active-p Determine whether a task is running. Function mp:process-active-p process process An object of type mp:process. Description Returns true if the task is currently running. mp:process-enable Start up a task which was not running. Function mp:process-enable process process An object of type mp:process. Description The argument to this function should be a process created by , which has a function associated as per but which is not yet running. After invoking this function a new thread will be created in which the associated function will be executed. Example The following is a possible implementation of . (defun process-run-function (process-name process-function &rest args) (let ((process (mp:make-process name))) (apply #'mp:process-preset process function args) (mp:process-enable process))) mp:process-kill Try to stop a running task. Function mp:process-kill process process An object of type mp:process. Description This function tries to stop a running task. Killing a process may fail if the task has disabled interrupts. Example Kill a task that is doing nothing. (flet ((task-to-be-killed () (loop (sleep 1)) ; Infinite loop )) (let ((task (mp:process-run-function 'background #'task-to-be-killed))) (sleep 10) (mp:process-kill task))) mp:process-name Return the name of a task. Function mp:process-name process process An object of type mp:process. Description Returns the name of the given task, if any. mp:process-preset Associate a function to a process. Function mp:process-preset process function &rest; function-args process An object of type mp:process. function An interpret or compiled function. function-args One or more arguments for the function above. Description This function associates a function to a stopped task. This function will be the entry point when the task is enabled in the future. See also . Example See . mp:process-run-function Create a task and execute a function in it. Function mp:process-run-function name function &rest; function-args name A symbol to name the process. Processes can be unnamed and names need not be unique. function A function object, interpreted or compiled. function-args One or more arguments which will be passed to the function. Description This function creates a new process using , associates a function to it and then starts it using . Example As an example, the following code starts a background task that outputs a list of numbers, one every second: (flet ((count-numbers (end-number) (dotimes (i end-number) (format t "~%;;; Counting: ~i" i) (terpri) (sleep 1)))) (mp:process-run-function 'counter #'count-numbers 10)) mp:recursive-lock-p Determine whether lock is recursive or not. Function mp:recursive-lock-p lock lock An object of type mp:lock. Description Returns true if the lock is recursive. mp:with-lock Synchronize a piece of code between different tasks. Macro mp::with-lock (lock) &body; body Description It grabs a lock, executes a piece of lisp code and releases the lock at the end. The inner forms are protected so that when any condition is signalled the lock is released. Example Ensure each task increments the counter properly. The lock is required because INCF is not an atomic operation. (defvar *counter* 0) (defvar *counter-lock* (mp:make-lock :name 'counter)) (flet ((task (name) (loop while (<= *counter* 10) do (progn (sleep 1) (with-lock (*counter-lock*) (format t "~%;;; ~A counts ~D" name *counter*) (terpri) (incf *counter*)))))) (mp:process-run-function 'ana #'task 'ana) (mp:process-run-function 'jose #'task 'jose))