From: Dave Yost
Subject: Re: throw-catch :cancel
Date: 
Message-ID: <3qv9e6$m4@Yost.com>
In article <·····················@[198.112.74.171]>,
>
>I've previously expressed the opinion that handling the cancel button on
>dialogs by doing a throw to :cancel is just a bad idea.  It should signal a
>condition, just like anything else.  This would allow the user to use a
>global condition handler instead of a stack-based one which wouldn't be
>applicable when the event is handled in another process.

Is the more general statement true?
Are throw/catch obsoleted by conditions in general?
(I came in after conditions were invented.)

Also, you seem to leave out the possibility of
per-thread condition handlers.  Did you mean to do that?

Dave Yost
    @    .com

From: Barry Margolin
Subject: Re: throw-catch :cancel
Date: 
Message-ID: <3r0vig$c1m@tools.near.net>
In article <·········@Yost.com> ····@Yost.com (Dave Yost) writes:
>In article <·····················@[198.112.74.171]>,
>>I've previously expressed the opinion that handling the cancel button on
>>dialogs by doing a throw to :cancel is just a bad idea.  It should signal a
>>condition, just like anything else.  This would allow the user to use a
>>global condition handler instead of a stack-based one which wouldn't be
>>applicable when the event is handled in another process.

The CL condition system doesn't have global condition handlers, only
stack-based ones.  Then again, CL doesn't have multiple threads, either; I
suppose an implementation that adds one could add the other as well.

Symbolics CL has global handlers, but I found that they were difficult to
use.  What if two applications both try to establish a global handler for
the same condition?

>Is the more general statement true?
>Are throw/catch obsoleted by conditions in general?

Conditions can be considered a generalization of throw/catch.  The tags in
catch and throw have to match exactly, while conditions use a hierarchy of
condition classes; thus, a handler for ERROR can catch a signal of
TYPE-ERROR.

In fact, conditions can (and often *are*) implemented using catch and
throw.
-- 
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@{bbnplanet.com,near.net,nic.near.net}
Phone (617) 873-3126 - Fax (617) 873-5124
From: Chris Riesbeck
Subject: Re: throw-catch :cancel
Date: 
Message-ID: <riesbeck-0606950927350001@riesbeck.ils.nwu.edu>
In article <··········@tools.near.net>, ······@nic.near.net (Barry
Margolin) wrote:

> The CL condition system doesn't have global condition handlers, only
> stack-based ones.  Then again, CL doesn't have multiple threads, either; I
> suppose an implementation that adds one could add the other as well.

In the discussion on comp.lang.lisp.mcl where this began, my solution
was to use BLOCK/RETURN-FROM rather than CATCH/THROW. I've included
the code below for reference.

Is this approach is guaranteed to work in any multi-threaded CL?



;;; A simple example of how to put up a window with a CANCEL button
;;; with a function attached that can interrupt a search process.
;;;
;;; Uses lexically-scoped BLOCK/RETURN-FROM tags rather
;;; than dynamically-scoped CATCH/THROW tags.
;;;
;;; Implementation notes:
;;;
;;; 1. The window is hidden until the UNWIND-PROTECT starts.
;;; 2. Instead of BLOCK, we could use (RETURN-FROM TEST-CANCEL ...).
;;; 3. For clarity and generality, both return values (:CANCELLED
;;;    and :FINISHED) are specified by the calling function.


(defun test-cancel ()
  (block search-loop
    (let ((w (make-button-window
              #'(lambda (dialog-item)
                  (declare (ignore dialog-item))
                  (return-from search-loop :cancelled)))))
      (unwind-protect
        (progn (window-show w)
               (dotimes (i 200 :finished) ;; standing in for a real search
                 (princ ".")))
        (window-close w)))))

(defun make-button-window (exit-fn)
  (make-instance 'window
    :window-show nil
    :view-position :centered
    :view-size ·@(100 100)
    :view-subviews (list (make-cancel-button exit-fn))))

(defun make-cancel-button (exit-fn)
  (make-dialog-item 'button-dialog-item
                    ·@(20 30) ·@(60 20)
                    "Cancel"
                    exit-fn))

-- 
Chris
From: Barry Margolin
Subject: Re: throw-catch :cancel
Date: 
Message-ID: <3r7pi3$m4v@tools.near.net>
In article <·························@riesbeck.ils.nwu.edu> ········@ils.nwu.edu (Chris Riesbeck) writes:
>In the discussion on comp.lang.lisp.mcl where this began, my solution
>was to use BLOCK/RETURN-FROM rather than CATCH/THROW. I've included
>the code below for reference.
>
>Is this approach is guaranteed to work in any multi-threaded CL?

Nothing is guaranteed, since there's no standard for multi-threaded CL.

I haven't seen the discussion in c.l.l.mcl, so I don't know what problem
you're trying to solve.  Do you want one thread to be able to cause a
function in another thread to return?  The only multi-threaded Lisp I have
lots of experience with is Symbolics CL, and I don't think it handled
RETURN or THROW from a different thread than the BLOCK or CATCH.
-- 
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@{bbnplanet.com,near.net,nic.near.net}
Phone (617) 873-3126 - Fax (617) 873-5124
From: Chris Riesbeck
Subject: Re: throw-catch :cancel
Date: 
Message-ID: <riesbeck-0906951724060001@riesbeck.ils.nwu.edu>
In article <··········@tools.near.net>, ······@nic.near.net (Barry
Margolin) wrote:

> ... Do you want one thread to be able to cause a
> function in another thread to return?  The only multi-threaded Lisp I have
> lots of experience with is Symbolics CL, and I don't think it handled
> RETURN or THROW from a different thread than the BLOCK or CATCH.

OK. Brain cells finally started working again and I re-read the
implementation note in Chapter 3 (p 44) and the scope/extent rules for
BLOCK tags. As I now understand it, the problem with code like this:

  In thread A:

    (block FOO
        -- start code running in thread B, passing it the closure
           #'(lambda () (return-from FOO nil))
     -- other stuff in block FOO, thread A)
    -- other stuff in thread A, after block FOO

is that FOO may be disestablished at any time in thread A.

The original MCL code explicitly deleted the closure in thread B
before exiting block FOO, so it's probably OK.

-- 
Chris