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:
* See: `man pthreads`
* See: `examples/concurrent_array_and_barrier.nit`
+* See: ̀ examples/threaded_example.nit`
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)
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
# `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
#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
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
class {{{classname}}}
super Thread
+ {{{vtype}}}
+
{{{params.join("\n")}}}
redef fun main do
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
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
threaded
10
parameterized and threaded
+main, waiting for baz
+baz result : 5