Merge: Parallelization phase improvement
authorJean Privat <jean@pryen.org>
Sat, 25 Apr 2015 02:18:54 +0000 (09:18 +0700)
committerJean Privat <jean@pryen.org>
Sat, 25 Apr 2015 02:18:54 +0000 (09:18 +0700)
Adds the support of methods with return value

If you use `is threaded` on a method with a return, it will instead return you a custom instance of `Thread` class on which you can use the method `join` to retrieve the return of the annotated method. `join` waits for the method to end before returning.If you want to make sure that the method has done his work before trying to retrieve it's return value, you can check it with the boolean `is_done`

Pull-Request: #1278
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Jean Privat <jean@pryen.org>

lib/pthreads/README.md
lib/pthreads/examples/threaded_example.nit
lib/pthreads/pthreads.nit
src/frontend/parallelization_phase.nit
tests/sav/threaded_example.res

index 4a117b4..44f3754 100644 (file)
@@ -12,7 +12,12 @@ This group also provides two optional modules with thread-safe collections:
 Theses services are implemented using the POSIX threads.
 
 You can also use the `is threaded` annotation on methods, which makes them run on their own thread.
-Methods with return value or self calls are not supported.
+Methods with self calls are not supported.
+
+A method or function annotated with `is threaded` has its return value changed during compilation.
+You will get a subclass of `Thread`, even if there wasn't a return value before. You can know if the threaded method is done with the `is_done` boolean from `Thread`.
+A call to the `join` method will block the execution until the threaded method is done, or immediatly return if it's already done.
+`join` will return an object typed with the orginial return type, or `null` if there wasn't.
 
 ## Known limitations:
 
@@ -24,3 +29,4 @@ Methods with return value or self calls are not supported.
 
 * See: `man pthreads`
 * See: `examples/concurrent_array_and_barrier.nit`
+* See: ̀ examples/threaded_example.nit`
index 9a0af4b..fb0609b 100644 (file)
@@ -32,7 +32,17 @@ fun bar(i : Int, s : String) is threaded do
        print s
 end
 
+# Parameterized `threaded` method with a return type
+fun baz(i : Int, j : Int): Int is threaded do
+       sys.nanosleep(10, 0)
+       return i + j
+end
+
+print "main"
 foo
 bar(10, "parameterized and threaded")
-print "main"
 sys.nanosleep(5,0)
+var x  = baz(2, 3)
+print "main, waiting for baz"
+var y = x.join
+print("baz result : " + y.to_s)
index 8b8de1f..afb66d6 100644 (file)
@@ -236,19 +236,26 @@ end
 abstract class Thread
        super Finalizable
 
+       # Type returned by `main`
+       type E : nullable Object
+
        private var native: nullable NativePthread = null
 
+       # Is this thread finished ? True when main returned
+       var is_done = false
+
        # Main method of this thread
        #
        # The returned valued is passed to the caller of `join`.
-       fun main: nullable Object do return null
+       fun main: E do return null
 
-       private fun main_intern: nullable Object
+       private fun main_intern: E
        do
                # Register thread local data
                sys.self_thread_key.set self
-
-               return main
+               var r = main
+               self.is_done = true
+               return r
        end
 
        # Start executing this thread
@@ -266,12 +273,12 @@ abstract class Thread
        # `Sys::thread_exit`. Returns the object returned from the other thread.
        #
        # Stats the thread if now already done by a call to `start`.
-       fun join: nullable Object
+       fun join: E
        do
                if native == null then start
                var r = native.join
                native = null
-               return r
+               return r.as(E)
        end
 
        redef fun finalize
index 2d15d82..08583da 100644 (file)
@@ -42,11 +42,6 @@ private class ParallelizationPhase
 
                #TODO: check for self calls
 
-               if nmethdef.n_signature.n_type != null then
-                       toolcontext.error(nat.location, "Error: functions not supported yet.")
-                       return
-               end
-
                # Get the module associated with this method
                var amod = nmethdef.parent.parent
                assert amod isa AModule
@@ -65,6 +60,18 @@ private class ParallelizationPhase
                        classname += nmethdef.n_methid.as(AIdMethid).n_id.text
                end
 
+               # Handle methods with a return value
+               var has_rvalue = nmethdef.n_signature.n_type != null
+               var vtype = ""
+               if has_rvalue then
+                       vtype = "redef type E: " + nmethdef.n_signature.n_type.n_id.text
+               end
+               # create a return type
+               var n_id = new TClassid
+               n_id.text = classname
+               var n_type = new AType
+               n_type.n_id = n_id
+               nmethdef.n_signature.n_type = n_type
 
                var params = new Array[String]
                # case if the method has parameters
@@ -82,6 +89,8 @@ var {{{param.n_id.text}}} : {{{param.n_type.n_id.text}}}
 class {{{classname}}}
        super Thread
 
+       {{{vtype}}}
+
        {{{params.join("\n")}}}
        redef fun main do
        end
@@ -102,11 +111,12 @@ end
                mainfun.n_block = nmethdef.n_block
 
                # Add "return null" to the end of the `main` function
-               var s_nullreturn = "return null"
-               var nullreturn = toolcontext.parse_something(s_nullreturn)
-               assert nullreturn isa AExpr
-               mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
-
+               if not has_rvalue then
+                       var s_nullreturn = "return null"
+                       var nullreturn = toolcontext.parse_something(s_nullreturn)
+                       assert nullreturn isa AExpr
+                       mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+               end
 
                # Create new body for the annotated fun
                var s_newbody : String
@@ -118,11 +128,13 @@ end
                        s_newbody ="""
 var thread = new {{{classname}}}({{{init_params.join(",")}}})
 thread.start
+return thread
 """
                else
                        s_newbody = """
 var thread = new {{{classname}}}
 thread.start
+return thread
 """
                end
 
index e90aa48..4f1025c 100644 (file)
@@ -2,3 +2,5 @@ main
 threaded
 10
 parameterized and threaded
+main, waiting for baz
+baz result : 5