Concurrency & Background tasks

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Concurrency & Background tasks

Hendrik Ebbers
I want to collect some ideas how the concurrency support for the JSR can be implemented. DataFX already has some APIs for concurrency and background tasks. Based on this JavaFX specific implementation I created a UIToolkit independent implementation some weeks ago. You can find an overview here: http://www.guigarage.com/2014/11/new-desktop-application-framework-datafx/

The implementation provides in the core a class that supports the following calls for threading concerns:

void runAndWait(Runnable runnable)
 
void runLater(Runnable runnable)
 
boolean isToolkitThread()
 
<T> T runCallableAndWait(Callable<T> callable)

I think that this methods can be implemented for any UI Toolkit to provide access to the UI thread.
In addition the API contains the ProcessChain that can be used to switch between the UI thread and background threads. By using the ProcessChain it's very easy to pass data for one thread to the other one. Here is an example:
ProcessChain.create().
    addSupplierInPlatformThread(() -> myTextField.getText()).
    addFunctionInExecutor((t) -> WeatherService.getWeather(t)).
    addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> {
        myLabel.setText("Error");
        e.printStackTrace();
    }).run();

This is how the concurrency support of DataFX would work in a general way.

How does the other frameworks (Griffon, JACPFX, etc.) handle this issues?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

tschulte
Hi,

I have recently started to use RxJava (https://github.com/ReactiveX/RxJava) for all asynchronous tasks. There exist special bindings for the toolkits, e.g. https://github.com/ReactiveX/RxJavaFX.

Your example with the weather service would look something like this (assuming the code is called from within the gui-thread):

Observable.just(myTextField.getText())
    .subscribeOn(Schedulers.io()).map((t) -> WeatherService.getWeather(t))
    .observeOn(uiScheduler).doOnError((e) -> {
        myLabel.setText("Error");
        e.printStackTrace();
    }).subscribe((t) -> myLabel.setText(t));

uiScheduler might be for example JavaFxScheduler.getInstance()

Another example (this time in Groovy): User selects some rows in a table and wants to execute an action on them (e.g. update something with a server):

ProgressMonitor progressMonitor = createProgressMonitor()

List<Long> selectedRowIds = getSelectedRows()

Observable.from(selectedRowIds)
    .subscribeOn(Schedulers.io()).map { updateStateOnServer(it) }
    .observeOn(uiScheduler)
    .doOnNext { progressMonitor.incrementProgress() }
    .finallyDo { progressMonitor.finished() }
    .subscribe { updateResult -> updateRow(updateResult) }

I have abstracted the updating of the progress away (still using Swing and JBusyComponent). My ObservableBusyModel does a little bit more than the above, e.g. handling of cancel, etc.

RxJava is very flexible, and therefore can be used for nearly everything (but the learning curve is steep).

But just to give another possibilty:

Observable.timer(30, 30, TimeUnit.SECONDS, Schedulers.io()).map { loadFromServer() }
    .observeOn(uiScheduler).subscribe { dataFromServer -> updateUi(dataFromServer) }

The above will poll the server every 30 seconds and update the ui with the new data.

Regards,

Tobias

On 02.01.2015 11:20, Hendrik Ebbers [via jsr377-api] wrote:
I want to collect some ideas how the concurrency support for the JSR can be implemented. DataFX already has some APIs for concurrency and background tasks. Based on this JavaFX specific implementation I created a UIToolkit independent implementation some weeks ago. You can find an overview here: http://www.guigarage.com/2014/11/new-desktop-application-framework-datafx/

The implementation provides in the core a class that supports the following calls for threading concerns:

void runAndWait(Runnable runnable)
 
void runLater(Runnable runnable)
 
boolean isToolkitThread()
 
<T> T runCallableAndWait(Callable<T> callable)

I think that this methods can be implemented for any UI Toolkit to provide access to the UI thread.
In addition the API contains the ProcessChain that can be used to switch between the UI thread and background threads. By using the ProcessChain it's very easy to pass data for one thread to the other one. Here is an example:
ProcessChain.create().
    addSupplierInPlatformThread(() -> myTextField.getText()).
    addFunctionInExecutor((t) -> WeatherService.getWeather(t)).
    addConsumerInPlatformThread((t) -> myLabel.setText(t)).onException((e) -> {
        myLabel.setText("Error");
        e.printStackTrace();
    }).run();

This is how the concurrency support of DataFX would work in a general way.

How does the other frameworks (Griffon, JACPFX, etc.) handle this issues?



If you reply to this email, your message will be added to the discussion below:
http://jsr377-api.40747.n7.nabble.com/Concurrency-Background-tasks-tp3.html
To start a new topic under jsr377-api, email [hidden email]
To unsubscribe from jsr377-api, click here.
NAML

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

aalmiray
Administrator
Hi all,

We definitely need to tackle this topic. I would rather err on the side of caution and provide a minimal abstraction for what can be done in relation to to the UI thread. The main toolkits provide the following behavior:

Swing:
  - runAndWait
  - runLater
  - isUIThread

JavaFX:
  - runLater
  - isUIThread

SWT:
  - runSync
  - runAsync
  - isUIThread

Based on this I'd suggest we create an abstraction that follows Swing/SWT. Such an abstraction already exists in Griffon too (see https://github.com/griffon/griffon/blob/development/subprojects/griffon-core/src/main/java/griffon/core/threading/ThreadingHandler.java). This interface defines a few more methods that may or may not be desired for the JSR.

If we were to follow the reactive approach (liek RxJava) we would miss the opportunity to properly handle runAndWait/runSync with toolkits that need this behavior. Additionally I'd prefer to follow a much more standard API than RxJava, that is, the Reactive API that RxJava, Akka and others implement; but this would mean adding an additional external dependency to the JSR API, which I'd rather avoid. Having external dependencies on the JSR RI otoh is OK. Given this, an observable, reactive approach would be better suited for implementors and not for the spec.

Thoughts?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Hendrik Ebbers
We need a core class that contains the default methods like:
 runAndWait
 runLater
 isUIThread

I like the idea to add basic method for background calls like:

void runOutsideUI(@Nonnull Runnable runnable);
<R> Future<R> runFutureOutsideUI(@Nonnull Callable<R> callable);

In addition I would add this method:
<T> T runAndWait(Callable<T> callable)

Based on the last two methods it is easy to define a reactive API that handles callbacks. In addition to the base methods we should provide a higher API like the ProcessChain, the SwingWorker or whatever to handle tasks that switch between the UI thread and background threads. I would avoid to add an external dependency to any reactive framework here. I think it's better to provide implementations as additional libs for the given framework like a library that provides RxJava based APIs that internally call our basic APIs. But this should not be part of the JSR. By doing so we are ready for any reactive framework. A developer can use the base APIs that are provided by the JSR. If he wants to use RxJava, Akka or whatever he needs to add an additional wrapper library or create a new open source one :)

About Executors:
When working on the UI thread you don't need executors but if you want to handle background tasks you should use executors. Sometimes you don't want to know what executor will handle your task. In this case you can simply use the described methods. But sometimes you want to run all your background tasks in a specific thread pool. In this case we should add the following methods:

void runOutsideUI(@Nonnull Runnable runnable, Executor e);
<R> Future<R> runFuture(@Nonnull Callable<R> callable, ExecutorService e);

The JSR should provide a special ExecutorService (thread pool) that will be used if you don't specify a special one. This executor should be configurable by the JSR (xml file?) and created at bootstrap as part of the application lifecycle.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Hendrik Ebbers
I don't know if this methods would make sense:
Future<T> runLater(Callable<T> callable)
Future<Void> runLater(Runnable runnable)

Maybe this can be helpful to provide a better support for reactive APIs.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

aalmiray
Administrator
In reply to this post by Hendrik Ebbers
Hendrik,

I agree on the 3 basic methods:

  void runAndWait(Runnable r)
  void runLater(Runnable r)
  boolean isUIThread()
The "runAndWait with Callable" variant can be written on top of the "runAndWait with Runnable" variant

  public <V> V runAndWait(Callable<V> callable) {
    FutureTask<V> ft = new FutureTask<V>(callable);
    runAndWait(ft);
    return ft.get();
  }
I don't know if your familiar on how runAndWait behaves in SWT vs. Swing, specifically when triggering an invocation inside the UI thread. This is permitted in SWT IIRC but Swing throws an exception right away. This is wrong in my opinion. The way I see it runAndWait should be implemented as follows

  // ugly pseudocode
  if isUIThread() runnable.run()
  then run_inside_ui_and_wait(runnable)
This behavior should be documented in the JSR API and guaranteed/enforced by the JSR TCK, that is, implementors should abide to the contract. Next we have the runOutsideUI variants, with implicit and explicit Executor

  void runOutsideUI(Runnable r)
  void runOutsideUI(Executor x, Runnable r)
  <V> V runOutsideUI(Callable<V> c)
  <V> V runOutsideUI(Executor x, Callable>V> c)
IMHO the JSR API should not force a specific default Executor, this is an implementation detail that implementors should decide on their own given whatever facilities they have at their disposal. In other words, the JSR spec defines that a default ExecutorService should be ready and available for implementations of the "threading handler" interface but does not impose a specific definition. The JSR RI and implementors will decide which ExecutorService to use. For this reason we decided in Griffon to follow a simple API approach: most type definitions found under the "griffon.core" package are interfaces or enums; specific implementations of said interfaces are found at the "org.codehaus.griffon" package, for example

https://github.com/griffon/griffon/blob/development/subprojects/griffon-core/src/main/java/griffon/core/threading/UIThreadManager.java

https://github.com/griffon/griffon/blob/development/subprojects/griffon-core/src/main/java/org/codehaus/griffon/runtime/core/threading/AbstractUIThreadManager.java

https://github.com/griffon/griffon/blob/development/subprojects/griffon-swing/src/main/java/org/codehaus/griffon/runtime/swing/SwingUIThreadManager.java

As you can see the AbstractUIThreadManager creates its own ExecutorService (in hindsight this instance should probable be injected, but that's an implementation detail ;-)

Circling back to the API design approach, I think this JSR should strive to create interfaces and enums under "javax.<?!?>" (akin to the "griffon.core" package), minimizing abstract and concretes classes as much as possible.

WDYT?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

tschulte
Hi,

On 06.01.2015 14:10, aalmiray [via jsr377-api] wrote:
that is, implementors should abide to the contract. Next we have the runOutsideUI variants, with implicit and explicit Executor

  void runOutsideUI(Runnable r)
  void runOutsideUI(Executor x, Runnable r)
  <V> V runOutsideUI(Callable<V> c)
  <V> V runOutsideUI(Executor x, Callable>V> c)


why is there a need for the explicit Executor variants? Won't they just delegate to the passed Executor? Is there a need for the ThreadingHandler to know each Runnable or Callable?

Otherwise one could even leave the runOutside methods out of the UIThreadingHandler and instead introduce an annotation for the default outside executor(s). Maybe even more than one, e.g. inspired by RxJava:

    @IO
    @Inject
    ExecutorService ioExecutor;
   
    @Computation
    @Inject
    ExecutorService computationExecutor;

That way the UIThreadingHandler could even be a sub interface of ExecutorService (with additional methods isUIThread() and runAndWait()) and could be used just the same using @UI. But then the method names would too generic, I think.

One drawback of injecting ExecutorServices would be, that everyone could call shutdown() and shutdownNow() on these ExecutorServices.

Some more questions:

Does the jsr only handle these basic methods, i.e. is handling progress like done in SwingWorker out of scope of the api? Or will this be part of a more high level part of the api which will use these low level methods?

What about cancelling runOutside calls?

Speaking of annotations. Will this JSR define Annotations like the Griffon @Threading AST? Maybe using CDI?

Regards,

Tobias
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Hendrik Ebbers
Hi,

I will comment the post of aalmiray and tschulte:

aalmiray wrote
The "runAndWait with Callable" variant can be written on top of the "runAndWait with Runnable" variant

  public <V> V runAndWait(Callable<V> callable) {
    FutureTask<V> ft = new FutureTask<V>(callable);
    runAndWait(ft);
    return ft.get();
  }
That's why I would use a default method in the interface :)

aalmiray wrote
I don't know if your familiar on how runAndWait behaves in SWT vs. Swing, specifically when triggering an invocation inside the UI thread. This is permitted in SWT IIRC but Swing throws an exception right away. This is wrong in my opinion. The way I see it runAndWait should be implemented as follows

  // ugly pseudocode
  if isUIThread() runnable.run()
  then run_inside_ui_and_wait(runnable)
This behavior should be documented in the JSR API and guaranteed/enforced by the JSR TCK, that is, implementors should abide to the contract
I don’t know if this is the best idea. I saw some Swing applications where developers created a „saveRunAndWait“ that does exactly the same. The result was that this method was called everywhere and in the end nobody knew what method is called in the UI thread or on a background thread. Throwing an exception will forbid this bad design. Maybe this can be a RuntimeException?
The behavior should be defined in the JSR.

aalmiray wrote
 void runOutsideUI(Runnable r)
  void runOutsideUI(Executor x, Runnable r)
  <V> V runOutsideUI(Callable<V> c)
  <V> V runOutsideUI(Executor x, Callable>V> c)
IMHO the JSR API should not force a specific default Executor, this is an implementation detail that implementors should decide on their own given whatever facilities they have at their disposal. In other words, the JSR spec defines that a default ExecutorService should be ready and available for implementations of the "threading handler" interface but does not impose a specific definition. The JSR RI and implementors will decide which ExecutorService to use.
Ok :)
My idea was to go a step further and provide a configuration definition for the default ExecutorService. As a first step it is definitely ok to let the implementation define this part. Maybe we can add this specs in a later version.


tschulte wrote
>       void runOutsideUI(Runnable r)
>       void runOutsideUI(Executor x, Runnable r)
>       <V> V runOutsideUI(Callable<V> c)
>       <V> V runOutsideUI(Executor x, Callable>V> c)
>
>

why is there a need for the explicit Executor variants? Won't they just
delegate to the passed Executor?
I think both version are important. In most cases you only want to call runOutside(runnable) to move a task to a background thread. But sometimes you need more control about this threads. In eclipse for example all background tasks are shown in the progress window. Here you see what tasks are running. Maybe you want to do the same with your desktop application. To do so you need your own special executor services that provides the needed functionality. Here is an example how you can do this with JavaFX / DataFX: http://www.guigarage.com/2013/02/datafx-observableexecutor-preview/
DataFX provides this type of executor as default, for example. But even that is not enough. Maybe you want to handle different types of tasks in different executors. If you have an application that can convert data and call rest services you could create a thread pool to do the conversion and another one to do the rest calls. In this case you need to pass your executor to the method. by doing so you could define a specific progress view for each task type, for example.


tschulte wrote
That way the UIThreadingHandler could even be a sub interface of ExecutorService (with additional methods isUIThread() and runAndWait()) and could be used just the same using @UI. But then the method names would too generic, I think.

One drawback of injecting ExecutorServices would be, that everyone could call shutdown() and shutdownNow() on these ExecutorServices.
I think that the shutdown methods are the big problem here. because of them I don't want to go this way.

tschulte wrote
Does the jsr only handle these basic methods, i.e. is handling progress
like done in SwingWorker out of scope of the api? Or will this be part
of a more high level part of the api which will use these low level methods?
I think the JSR should handle both. The core classes are only interfaces that will be implemented by the Frameworks that depend on the JSR (for example DataFX for JavaFX, etc.). But based on this core classes we can provide some APIs (implemented classes) that provide a higher level like SwingWorker or ProcessChain. But I think this topic need to be discussed because as far as I unterstand Andres he only want the core interfaces to be part of the JSR, right?

tschulte wrote
What about cancelling runOutside calls?
As I described above I think that these methods are important.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Sébastien Bordes
Hello everybody,

If I understand well the JSR will contain only a standard API for all application frameworks. It shall contain only interfaces (with a minimum of default method), enumeration and for sure annotations.

I have done this job for JRebirth Application Framework, I have extracted all these classes into an API artifact, the Javadoc is available here: http://sites.jrebirth.org/org.jrebirth-8.0.0-SNAPSHOT/api/apidocs/
I could explain in another topic how JRebirth works if you are interested, it has a custom pattern with 3 levels (WB-CS-MVC => Wave Behavior-Command Service - Model View Controller).

Concerning the concurrent topic JRebirth has already an engine that manage them.
You can see the base API here: http://sites.jrebirth.org/org.jrebirth-8.0.0-SNAPSHOT/api/apidocs/org/jrebirth/af/api/concurrent/package-summary.html

The main principle is the separation of thread type (doc here : http://sites.jrebirth.org/org.jrebirth-8.0.0-SNAPSHOT/doc/Thread.html).

JRebirth does it with 3 kinds of thread performed in 4 contexts:

    JAT - JavaFX Application Thread
    JIT - JRebirth Internal Thread
    JTP - JRebirth Thread Pool (name pattern is JTP Slot 'n' )
    HPTP - High Priority Thread Pool (name pattern is HPTP Slot 'n' )

The JAT is the JavaFX Application Thread, the GUI you know well.
The JIT will handle an event bus called Notifier managing message called Wave
The JTP is a ThreadPool with a parameterized size (default is a ratio of CPU cores)
The HPTP is a second ThreadPool used to manage runnable that has an higher priority when the JTP is full (update made for dooapp team)

It's possible to use RunInto annotaion on a method to declare how it should be run, but it's only supported in conjunction of the Event Bus of JRebirth, otherwise bytecode manipulation will be required to wrap each method.

JRebirth has also an utility class named JRebirth :) that offers some shortcuts
static void checkJAT()
Check if the current code is executed into the JavaFX Application Thread otherwise throws an exception.
static void checkJIT()
Check if the current code is executed into the JRebirthThread otherwise throws an exception.
static void checkJTPSlot()
Check if the current code is executed into one slot of the JRebirth Thread Pool otherwise throws an exception.

static boolean isJAT()
Return true if we are into the JavaFX Application Thread (JAT).
static boolean isJIT()
Return true if we are into the JRebirth Internal Thread (JIT).
static boolean isJTPSlot()
Return true if we are into a slot of the thread pool (JTP).
static void run(RunType runInto, JRebirthRunnable runnable)
Run the task into the appropriated thread.
static void runIntoJAT(JRebirthRunnable runnable)
Run the task into the JavaFX Application Thread [JAT].
static void runIntoJIT(JRebirthRunnable runnable)
Run into the JRebirth Internal Thread [JIT].
static void runIntoJTP(JRebirthRunnable runnable)
Run into the JRebirth Thread Pool [JTP].

But in my opinion the application framework should hide the threading complexity and the API should provide really simply named methods otherwise developpers will not take over it.

Hope it helps the discussion

Seb






 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Hendrik Ebbers
I started to blog about my thoughts at guigarage. By doing so I can embed code and images. Here is the first blog post that contains some basics about UI Concurrency: http://www.guigarage.com/2015/01/concurrency-ui-toolkits-part-1/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

aalmiray
Administrator
Thanks Hendrik. This is a good way to continue exploring the possibilities :-)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Concurrency & Background tasks

Hendrik Ebbers
Loading...