Merge: Intro `Task` and use in for Android's `run_on_ui_thread`
authorJean Privat <jean@pryen.org>
Thu, 5 Nov 2015 15:13:53 +0000 (10:13 -0500)
committerJean Privat <jean@pryen.org>
Thu, 5 Nov 2015 15:13:53 +0000 (10:13 -0500)
The `Task` interface defines a fragment of Nit code to execute in its `main` method. This interface should be compatible between different platforms and parallelization engines.

`NativeActivity::run_on_ui_thread` is widely used on Android as most logic is executed on background threads but only the UI thread can modify the UI. It is a perfect example of how the `Task` interface can be used.

Future work include using `Task` in `pthreads` and `gtk::gdk`. But there a a few differences in the logic that makes it not as easy: `Thread::main` returns a `nullable object`, but is it worth keeping it? `GdkRunnable::run` returns a boolean to tell GDK if it should be called again.

Pull-Request: #1812
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Romain Chanoir <romain.chanoir@viacesi.fr>

contrib/nitester/src/nitester.nit
lib/android/activities.nit
lib/core/kernel.nit
tests/sav/error_class_glob.res
tests/sav/nituml_args3.res
tests/sav/nituml_args4.res

index 8f28415..0904053 100644 (file)
@@ -170,7 +170,7 @@ abstract class Processor
        end
 
        # All tasks to be performed
-       var tasks = new Array[Task]
+       var tasks = new Array[TesterTask]
 
        # Gather and register all tasks
        fun create_tasks
@@ -193,7 +193,7 @@ abstract class Processor
                                continue label
                        end
 
-                       tasks.add new Task(engine, prog)
+                       tasks.add new TesterTask(engine, prog)
                end label
        end
 end
@@ -429,7 +429,7 @@ class Worker
        # Single C `int` to hold the next task id received from the `Controller`
        var task_buffer = new CIntArray(1)
 
-       # Manage communication with the `Controller` and execute dispatched `Task`s
+       # Manage communication with the `Controller` and execute dispatched `TesterTask`s
        fun work_on_tasks
        do
                var status = new Status
@@ -566,7 +566,7 @@ end
 #
 # Note that a task may involve more than one program to test considering the
 # alts and args for the `test_program`.
-class Task
+class TesterTask
        # Engine to test executing `test_program`
        var engine: String
 
@@ -576,12 +576,12 @@ class Task
        redef fun to_s do return "{engine} {test_program}"
 end
 
-# Result of a `Task`
+# Result of a `TesterTask`
 #
-# There may be more than one result per `Task`.
+# There may be more than one result per `TesterTask`.
 class Result
-       # `Task` associated to `self`
-       var task: Task
+       # `TesterTask` associated to `self`
+       var task: TesterTask
 
        # Argument index of the execution resulting in `self`
        var arg: Int
index ed8e1f6..a457899 100644 (file)
@@ -40,4 +40,16 @@ extern class NativeActivity in "Java" `{ android.app.Activity `}
 
        # Notify the OS that this activity is done and should be closed
        fun finish in "Java" `{ self.finish(); `}
+
+       # Execute `task.main` on the UI thread when possible
+       fun run_on_ui_thread(task: Task) import Task.main in "Java" `{
+               final int final_task = task;
+               Runnable runnable = new Runnable() {
+                       @Override
+                       public void run() {
+                               Task_main(final_task);
+                       }
+               };
+               self.runOnUiThread(runnable);
+       `}
 end
index 650360a..84bd844 100644 (file)
@@ -1067,3 +1067,14 @@ extern class Pointer
        # Free the memory pointed by this pointer
        fun free `{ free(self); `}
 end
+
+# Task with a `main` method to be implemented by subclasses
+#
+# This class is provided for compatibility between different parallelization systems.
+# It can be used to run a fragment of code on a different thread and
+# to register a reaction to UI events.
+interface Task
+
+       # Main method of this task
+       fun main do end
+end
index 3d8ae36..08a096b 100644 (file)
@@ -10,3 +10,4 @@
 ../lib/core/kernel.nit:704,1--890,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:892,1--1060,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:1062,1--1069,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1071,1--1080,3: Error: `kernel#Task` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
index 700f951..ec356da 100644 (file)
@@ -72,6 +72,11 @@ Pointer [
 ]
 Object -> Pointer [dir=back arrowtail=open style=dashed];
 
+Task [
+ label = "{interface\nTask||+ main()\l}"
+]
+Object -> Task [dir=back arrowtail=open style=dashed];
+
 A [
  label = "{A|- _vpubA: nullable A\l- _vproA: nullable A\l- _vpriA: nullable A\l- _vpubA2: A\l- _vproA2: A\l- _vpriA2: A\l- _vpriB: nullable B\l- _vpriB2: B\l|+ pubA(a: A)\l# proA(a: A)\l- priA(a: A)\l+ vpubA(): nullable A\l+ vpubA=(vpubA: nullable A)\l# vproA(): nullable A\l# vproA=(vproA: nullable A)\l- vpriA(): nullable A\l- vpriA=(vpriA: nullable A)\l+ vpubA2(): A\l+ vpubA2=(vpubA2: A)\l# vproA2(): A\l# vproA2=(vproA2: A)\l- vpriA2(): A\l- vpriA2=(vpriA2: A)\l- priB(a: B)\l- vpriB(): nullable B\l- vpriB=(vpriB: nullable B)\l- vpriB2(): B\l- vpriB2=(vpriB2: B)\l}"
 ]
index f01534c..a87d928 100644 (file)
@@ -72,6 +72,11 @@ Pointer [
 ]
 Object -> Pointer [dir=back arrowtail=open style=dashed];
 
+Task [
+ label = "{interface\nTask||+ main()\l}"
+]
+Object -> Task [dir=back arrowtail=open style=dashed];
+
 A [
  label = "{A||+ pubA(a: A)\l+ vpubA(): nullable A\l+ vpubA=(vpubA: nullable A)\l+ vpubA2(): A\l+ vpubA2=(vpubA2: A)\l}"
 ]