Possible language changes

Kevlin Henney kevlin at curbralan.com
Sun Mar 6 15:30:43 GMT 2005


In message <4229050B.7050408 at cs.oswego.edu>, Doug Lea <dl at cs.oswego.edu>
writes
>The combination of replies from Kevlin, Hans, and Doug Schmidt put me
>in the surprising position of suggesting that we (you) consider
>adopting something straight out of java.util.concurrent:
>
>An "Executor" is a something that can run code (submitted as
>   closures. In Java Runnables and Callables). One implementation
>   of an Executor is one that spawns a thread on each call to
>   execute. Another is a thread pool. Another
>    is something that just invokes the code in the current thread.

Yup, this is a good starting place, and is the role that a Threader
plays in the model I outlined.

>A Future represents the results of that action, that you can
>    retrieve, wait for, and/or try to cancel.

A specific application of futures is the Joiner approach I outlined.

>An ExecutorService is an Executor that has a controllable
>   lifecycle -- you can shut it down etc, -- and can in general
>   support execution of many actions
>
>The advantages here of something along these lines are that it
>punts on what exactly consititutes a Thread; thus bypassing
>the issue that is least likely to find consensus.

Agreed. This approach has close parallels with the reasons I took the
approach I did!

>A C++ system could support this API without ever exposing what it
>considers to be a thread. However, conversely, all existing thread-based
>subsystems can fairly easily support this API.

Definitely. My proof-of-concept was based on C wrappings and an existing
C++ library wrapping.

>I don't pretend that exactly this API makes sense for C++,
>so haven't tried to translate.
>
>And I'm not even particularly advocating this. It just struck me
>as alternative that more people could agree on than the others
>we've discussed so far.
>
>public interface Executor {
>    void execute(Runnable command);
>}

>From the C++ perspective, if the generic-programming style of the STL is
followed, this would be expressed as category of syntactic and semantic
requirements, much like the Threader pseudo-class I sketched. Given
these concepts, it is typical for a generic library to supply one or
more standard implementations that satisfy the requirements.

Likewise the Runnable interface is replaced by something that parallels
the Threadable concept, which should support both plain functions and
zero-argument function objects that include their return type declared
as a trait. I would also suggest that the function-call interface is
used for Executor.

Regardless of what names are chosen for the concepts (Executor vs
Threader, Threadable vs Runnable) or the concrete implementations
provided by a library, one difference in the interface I would consider,
based on the model I outlined, is that an Executor return a future. This
more closely follows the notion of threads as asynchronous functions in
C++. There is no direct equivalent to this in Java.

So, an example executor would look like the following:

        class threader
        {
        public:
                template<typename Threadable>
                  joiner<result_of<Threadable>::type>
                    operator()(const Threadable &);
                ...
        };

This uses the result_of trait-lookup class proposed for TR1.

Simply presenting the concept requirements -- which are minimal and easy
to explain -- and an example fragment offers enough detail for concrete
discussion but enough latitude for future detail and implementations.

>public interface Future<V> {
>    boolean cancel(boolean mayInterruptIfRunning);
>    boolean isCancelled();
>    boolean isDone();
>    V get() throws InterruptedException, ExecutionException;
>    V get(long timeout, TimeUnit unit)
>        throws InterruptedException, ExecutionException,
>               TimeoutException;;
>}

Again this can be represented as a category of requirements, which the
assumption that a standard library can offer one or more concrete
implementations. However, I would tend to something more minimal at the
moment: omit cancellability and time-out handling for the moment. The
former because it is a minefield that often sidetracks constructive
discussion on threading as a whole and the latter because there is a
notional dependency on any other date-time facilities that could be
introduced. In other words, just keep the idea of a future simple and, I
would propose, function-like for the moment, before adding further
detail to the discussion.

>public interface ExecutorService extends Executor {
>    void shutdown();
>    List<Runnable> shutdownNow();
>    boolean isShutdown();
>    boolean isTerminated();
>    boolean awaitTermination(long timeout, TimeUnit unit)
>        throws InterruptedException;
>    <T> Future<T> submit(Callable<T> task);
>    <T> Future<T> submit(Runnable task, T result);
>    Future<?> submit(Runnable task);
>    <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
>        throws InterruptedException;
>    <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
>                                  long timeout, TimeUnit unit)
>        throws InterruptedException;
>    <T> T invokeAny(Collection<Callable<T>> tasks)
>        throws InterruptedException, ExecutionException;
>    <T> T invokeAny(Collection<Callable<T>> tasks,
>                    long timeout, TimeUnit unit)
>        throws InterruptedException, ExecutionException,
>               TimeoutException;
>}

I think that outlining anything like this at this stage would be more
detail than would be appropriate for the level or kind of discussion
that we want to inspire. The more minimal model presented above offers
enough to show that a threading model can be introduced that is useful
and realistic wrt existing C and C++ threading libraries, and creates in
the language a need to discuss a coherent memory model, but it does not
draw the discussion into the trickier question of designing a fuller set
of concurrency facilities at this stage. However, I would strongly
support mentioning java.util.concurrent in the text as outlining a
direction that such facilities could take.

Thoughts?

Kevlin
-- 
____________________________________________________________

  Kevlin Henney                   phone:  +44 117 942 2990
  mailto:kevlin at curbralan.com     mobile: +44 7801 073 508
  http://www.curbralan.com        fax:    +44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review
____________________________________________________________






More information about the cpp-threads mailing list