Question

I am trying to create a process that uses a let*. When I try to run it, the child process is in a [reset] state. If I use a workaround and use let, the thread starts out as [active] everything works fine.

I am puzzled at this behavior and would love an explanation.

(defparameter *g* 1)
(defparameter *res-list* nil)

(defun tester ()
  (let ((res *g*))
    (push res *res-list*)))

CL-USER> (ccl:process-run-function "test" 'tester)
#<PROCESS test(4856) [Active] #x3020036E30AD>
CL-USER> *res-list*
(1)

Everything works so far. But if I change the let to let*, I get a [reset] state, but the code within the child thread is executed.

(defun tester ()
  (let* ((res *g*))
    (push res *res-list*)))

CL-USER> (ccl:process-run-function "test" 'tester)
#<PROCESS test(4862) [Reset] #x3020036BCF2D>
CL-USER> *res-list*
(1 1)

I would also be thankful if someone could point me to a resource which would explain the different states.

Thanks.

Was it helpful?

Solution

The different results are not because of let and let*. Processes can be in different states, and you're just seeing different results based on when you're catching the process to print it. When I run your code at the command line, I get mostly "Reset", but also some "Exhausted" and "Dead".

$ ccl64 
Welcome to Clozure Common Lisp Version 1.7-r14925M  (LinuxX8664)!
? (defparameter *g* 1)
*G*
? (defparameter *res-list* nil)
*RES-LIST*
? (defun tester ()
    (let ((res *g*))
      (push res *res-list*)))
TESTER
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(2) [Exhausted] #x30200058FDBD>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(3) [Reset] #x30200058CB3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(4) [Reset] #x30200058AB3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(7) [Dead] #x302000584B3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(8) [Reset] #x302000582B3D>

The manual doesn't say a whole lot about these different states, as far as I can tell, but it does have this, which should be enough to get you digging into other parts of the manual:

7.3.2. As of August 2003:

  • It's not clear that exposing PROCESS-SUSPEND/PROCESS-RESUME is a good idea: it's not clear that they offer ways to win, and it's clear that they offer ways to lose.

  • It has traditionally been possible to reset and enable a process that's "exhausted" . (As used here, the term "exhausted" means that the process's initial function has run and returned and the underlying native thread has been deallocated.) One of the principal uses of PROCESS-RESET is to "recycle" threads; enabling an exhausted process involves creating a new native thread (and stacks and synchronization objects and ...),and this is the sort of overhead that such a recycling scheme is seeking to avoid. It might be worth trying to tighten things up and declare that it's an error to apply PROCESS-ENABLE to an exhausted thread (and to make PROCESS-ENABLE detect this error.)

  • When native threads that aren't created by Clozure CL first call into lisp, a "foreign process" is created, and that process is given its own set of initial bindings and set up to look mostly like a process that had been created by MAKE-PROCESS. The life cycle of a foreign process is certainly different from that of a lisp-created one: it doesn't make sense to reset/preset/enable a foreign process, and attempts to perform these operations should be detected and treated as errors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top