[armedbear-devel] threads, join, clos

Tobias C. Rittweiler tcr at freebits.de
Sun Apr 25 15:36:18 UTC 2010

David Kirkman <dkirkman at ucsd.edu> writes:

> On Sat, Apr 24, 2010 at 5:21 PM, Tobias C. Rittweiler <tcr at freebits.de> wrote:
> > >
> > > Well, in the original patch it just returned the first value, and the second
> > > value is the completed/interrupted flag.  That's on obvious error, so I'm
> > > attaching a new patch that returns all of the values, plus the completed
> > > interrupted flag (for a function returning (values 1 2) thread-join will now
> > > return 1, 2, T)
> >
> > That strictly couples the caller with its return sites; pain that
> > multiple values are usually supposed to obliterate from.
> >
> >
> I think that the biggest problem with returning a status code at the
> end of multiple values is that if you want to write a wrapper to
> change the way the call operates (e.g. if you want to write a
> sb-thread-join that throws like the sbcl version) at some point you've
> got to convert the multiple values into a list, strip off the last
> element, and then convert the list back into multiple values -- which
> seems a bit inelegant.

Yes, and inefficient, at least with the MV tools provided by CL. 

> > > > At the project I'm currently working on, I added the following wrapper:
> > > >
> > > >  (defun join-thread (thread &key timeout
> > > >                                  (on-timeout :timeout)
> > > >                                  (on-failure :error))
> > > >    ...)
> > > >
> > > > The ON-TIMEOUT/FAILURE arguments are returned as primary results, making
> > > > it potentially ambiguous (does :error come from the return value of the
> > > > thread or because of a failure?); however the user can specify these
> > > > values -- and the user should almost always know in what range a
> > > > thread's return value is going to be -- so it's my humble opinion on how
> > > > I think JOIN-THREAD should look like. :-)
> > > >
> This version looks very convenient to use most of the time.  But it's
> not easy to write a generic wrapper to change the semantics without
> knowing the allowed return values of the underlying function.  Or is
> it?  (That's a real question!)

My argument is in the passage you quoted. The API above is convenient
without restricting flexibility.

It's a known trick, but perhaps it's new to you, so let me show you can
use the above function to do regardless of knowing the return value(s)
of the thread:

  (let* ((timeout-dummy (list :timeout))
         (failure-dummy (list :failure))
         (result (multiple-value-list
                   (join-thread thread :timeout <n>
                                :on-timeout timeout-dummy
                                :on-failure failure-dummy))))
    (cond ((eq result timeout-dummy)
           ...handle timeout...)
          ((eq result failure-dummy)
           ...handle failure...)
           (values-list result)))) ; or frob however you want

To the quickly-skimming reader:

Please note that the above is the most general case, and not what you'll
need most of the time. It's very unlikely that you want to join a thread
without knowing anything about it.

To David:

The above works because LIST will create a new cons which is unique
across the image.

The only debatable point I see is that perhaps :ON-TIMEOUT/FAILURE should
be made such that JOIN-THREAD will return the ON-TIMEOUT/FAILURE
argument as _secondary_ rather than primary value. This trades off the
common case of a thread only wanting to return one value for a little
bit added complexity for the general case depicted above.

> It could be made fully general if we add an interrupted flag to
> LispThread, and a function for querying it.  I think that way
> thread-join is easy to use most of the time, but if there is
> uncertainty to if :error is an allowed return value you can just
> query the thread to see if it completed normally.

So you'd have a THREAD-ABORTED-P function. Sure that'd do, too.

But then there's still the problem of how to indicate the timeout?

> Whatever we do, we should have a timeout keyword.
> I'm happy to change things, if we can agree what to change them to!

Someone from the ABCL team should decide. They can also document any API
decision as experimental, thus reserving the right to modify it if the
need should arise.


More information about the armedbear-devel mailing list