[threads-standard-discuss] MP standardization proposal

Robert Strandh strandh at labri.fr
Mon Jul 12 12:36:51 UTC 2004


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

-- 
Robert Strandh

---------------------------------------------------------------------
Greenspun's Tenth Rule of Programming: any sufficiently complicated C
or Fortran program contains an ad hoc informally-specified bug-ridden
slow implementation of half of Common Lisp.
---------------------------------------------------------------------




More information about the Threads-standard-discuss mailing list