Daniel Barlow writes:
* Process Creation
make-process function &key name [Function]
Creates a process named NAME. The new process will evaluate the function FUNCTION. On systems that do not support multi-processing, make-process will signal an error.
Three problems. First, the function is not evaluated but called (I suppose). Second, we should specify how the function is called. Third, we should say what the return value is. For instance:
* Process Creation
make-process function &key name [Function]
Creates a process named NAME. The new process will call the function FUNCTION with no arguments. The default value for name is NIL. The value returned is the newly created process. On systems that do not support multi-processing, make-process will signal an error.
*default-special-bindings*
This variable holds an alist associating special variable symbols with forms to evaluate for binding values. Special variables named in this list will be locally bound in the new process.
This may be rebound around calls to MAKE-PROCESS to add/alter default
Preferable: This variable may...
bindings. The effect of mutating this list is undefined, but earlier forms take precedence over later forms for the same symbol, so defaults may be overridden by consing to the head of the list.
[ Forms are evaluated in the new thread or in the calling thread? ]
I suggest in the old process so that the new process can have its behavior modified by the creating process.
[ Standard contents of this list: print/reader control, etc. Can borrow the franz equivalent? ]
Initial values of other special variables are implementation-defined. For example, they may be the same as in the process that called make-process, or set from the global values of the variables.
Well, it would be useful to standardize what happens to variables that are not rebound by the process that called make-process. For instance:
Initial values of other special variables that have not been bound by the process calling make-process preserve their values. Initial values of other special variables that have been bound by the process calling make-process are implementation-defined. For example ...
The new thread may rebind special variables: the new bindings are local to that thread. If it assigns to special variables that have not been bound (either at process creation time or subsequently), the effect is implementation-defined.
I would think relying on the global binding to be shared would be an important programming technique so that you can communicate between processes. No?
process-name process [Function]
Returns the name of the process, as supplied to MAKE-PROCESS
"or NIL if no name was supplied to MAKE-PROCESS." ?
- Atomic operations
atomic-incf reference [Function] atomic-decf reference [Function]
Were these meant to be "[Macro]"?
What is a reference? The same thing as a place? Less general?
Increments (or decrements) the fixnum value referred to by reference as a single, atomic operation. If the operation would take the value out of fixnum range, behaviour is undefined.
We should specify what value is returned, for instance:
The value of the call is the fixnum after incrementation.
- Resource contention: locks and recursive locks
make-lock &optional name [Function]
Creates a lock (a mutex) whose name is NAME. If the system does not support multiple processes this will still return some object, but it may not be used for very much.
[ in CLIM-SYS this is a freshly consed list (NIL). I don't know if there's some good reason it should be said structure or that it be freshly consed - EQ comparison of locks? ]
I do not think there is a good reason to specify what is returned.
acquire-lock lock &optional (wait-p t) [Function]
Acquire the lock LOCK for the calling process. If the lock is not available, and if WAIT-P is non-NIL, wait until it is.
Specify return values and what happens when WAIT-P is NIL:
Acquire the lock LOCK for the calling process. Return true if the lock was successfully acquired, and NIL otherwise. If the lock is not available, and if WAIT-P is non-NIL, wait until it is. Thus if WAIT-P is non-NIL, ACQUIRE-LOCK will always return true (if it returns at all). If WAIT-P is NIL and the lock is not available, ACQUIRE-LOCK immediately returns NIL.
This specification does not define what happens if a process attempts to acquire a lock that it already holds. For applications that require locks to be safe when acquired recursively, see instead MAKE-RECURSIVE-LOCK and friends.
release-lock lock [Function]
Release LOCK. It is an error to call this unless the lock has previously been acquired (and not released) by the same process. If other processes are waiting for the lock, the ACQUIRE-LOCK call in one of them will now be able to continue.
Specify return value?
with-lock-held (place) &body body [Macro]
Evaluates BODY with the lock named by PLACE, which is a reference to a lock created by MAKE-LOCK.
Evaluates BODY with the lock named by PLACE, the value of which is a lock created by MAKE-LOCK. Before the forms in BODY are evaluated, the lock is acquired using ACQUIRE-LOCK. After the forms in BODY have been evaluated, the lock is released using RELEASE-LOCK.
The lock will still be released even if a non-local control transfer (e.g. by THROW or SIGNAL) is signalled, but
I suspect one does not say that a throw is "signalled" (which is my book is spelled "signaled" so as to avoid an emphasis on the `a'). Perhaps :
The lock will still be released even if a non-local control transfer (e.g. by THROW or SIGNAL) terminates the execution of BODY, but
note that if the debugger is entered, the lock may only be released /after/ execution has been restarted.
"may" is an unfortunate word in English. It could mean that the programmer does not have the right to release it, or that it might be released.
If the process is unable to acquire the lock, BODY will not be evaluated.
This phrase seems superfluous.
Perhaps we should allow for a value of WAIT-P to be passed to ACQUIRE-LOCK? If so, specify what happens when WAIT-P is nil and the lock could not be acquired.
make-recursive-lock &optional name [Function]
Creates a recursive lock whose name is NAME. A recursive lock differs from an ordinary lock in that a process that already holds the recursive lock can acquire it again without blocking. The process must then release the lock twice before it becomes available for another process.
Specify return value.
acquire-recursive-lock lock [Function]
Perhaps use different return values depending on whether the lock is already held or not.
Why do we need a different function here?
As for ACQUIRE-LOCK, but for recursive locks.
release-recursive-lock lock [Function]
Idem.
Release the recursive LOCK. The lock will only become free after as many Release operations as there have been Acquire operations. See RELEASE-LOCK for other information.
with-recursive-lock-held (place &key timeout) &body body [Macro]
Idem.
Evaluates BODY with the recursive lock named by PLACE, which is a reference to a recursive lock created by MAKE-RECURSIVE-LOCK. See WITH-LOCK-HELD etc etc