From: Jean Privat Date: Thu, 5 Nov 2015 15:13:53 +0000 (-0500) Subject: Merge: Intro `Task` and use in for Android's `run_on_ui_thread` X-Git-Tag: v0.8~107 X-Git-Url: http://nitlanguage.org?hp=aa7b441eeed93caa92a681453d5eb69062789d9a Merge: Intro `Task` and use in for Android's `run_on_ui_thread` 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 Reviewed-by: Romain Chanoir --- diff --git a/contrib/nitester/src/nitester.nit b/contrib/nitester/src/nitester.nit index 8f28415..0904053 100644 --- a/contrib/nitester/src/nitester.nit +++ b/contrib/nitester/src/nitester.nit @@ -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 diff --git a/lib/android/activities.nit b/lib/android/activities.nit index ed8e1f6..a457899 100644 --- a/lib/android/activities.nit +++ b/lib/android/activities.nit @@ -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 diff --git a/lib/core/kernel.nit b/lib/core/kernel.nit index 650360a..84bd844 100644 --- a/lib/core/kernel.nit +++ b/lib/core/kernel.nit @@ -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 diff --git a/tests/sav/error_class_glob.res b/tests/sav/error_class_glob.res index 3d8ae36..08a096b 100644 --- a/tests/sav/error_class_glob.res +++ b/tests/sav/error_class_glob.res @@ -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`? diff --git a/tests/sav/nituml_args3.res b/tests/sav/nituml_args3.res index 700f951..ec356da 100644 --- a/tests/sav/nituml_args3.res +++ b/tests/sav/nituml_args3.res @@ -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}" ] diff --git a/tests/sav/nituml_args4.res b/tests/sav/nituml_args4.res index f01534c..a87d928 100644 --- a/tests/sav/nituml_args4.res +++ b/tests/sav/nituml_args4.res @@ -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}" ]