### Concurrency Functions #### startthread Starts a thread of execution that executes the passed callback. The function immediately returns a special object, that can be used with #link: awaitresult# , to get the value returned from the callback, after it has finished execution in the thread. This can also be used with #link: killthread# to stop the execution of a thread. The first argument to this function is the function that should be run in the thread. The second argument is passed to the thread function. If you want to pass multiple values, then you can simply wrap the values in a list, and pass the list to the thread. The thread function inherits scope from main thread in a readonly way. This means that any change made to the variables from the thread will not be visible from the main thread. If you have to share some data with the thread that should be modified by the thread, you have to use a mutable reference, passed to the thread function using the second argument to `startthread` function. Example: If you run the following program, you can see that the functions `thread1` and `thread2` being run concurrently. ``` proc thread1(threadname) for i = 1 to 10 println(threadname) wait(1) endfor endproc proc thread2(threadname) for i = 1 to 10 println(threadname) wait(1) endfor endproc let t1 = startthread(thread1, "thread 1") let t2 = startthread(thread2, "thread 2") await(t1) await(t2) waitforkey() ``` #### killthread Kill a thread using the object returned by the `startthread` function. Example: ``` proc thread1(threadname) loop println("loop") wait(1) endloop endproc let t1 = startthread(thread1, "thread 1") wait(3) -- Wait 3 seconds killthread(t1) println("Thread killed") waitforkey() ``` #### awaitresult Wait till the procedure in corresponding thread finish executing and return the result. If the thread function does not return a value, that will be a runtime error. Example: ``` proc thread1(threadname) wait(3) return 100 endproc let t1 = startthread(thread1, "thread 1") println("Thread started, waiting for result...") println(awaitresult(t1)) waitforkey() ``` #### await Just wait till the procedure in corresponding thread finish executing. Does not expect the thread callback to return a value. Example: ``` proc thread1(threadname) wait(3) endproc let t1 = startthread(thread1, "thread 1") println("Thread started, waiting to end...") await(t1) println("Thread finished") waitforkey() ``` #### newchannel Create a new channel. A channel enables values to be sent and receieved between multiple threads. Example: In the following program, we use a channel to get values sent from a thread. We first create a channel, then start a thread passing the channel to it. In the thread we use the #link: writechannel# function to write a value to the channel every second. In the main thead, we wait on the channel using the #link: readchannel# function and just print the values receieved on the channel. ``` proc thread1(args) loop writechannel(args[2], 20) wait(1) endloop endproc let ch = newchannel() let t1 = startthread(thread1, ["thread 1", ch]) println("Thread started, waiting for result...") loop let x = readchannel(ch) println(x) endloop waitforkey() ``` #### writechannel Write a value to a channel. See #link: newchannel# for an example. #### readchannel ``` let msg = readchannel(channel) ``` Wait till a value is available on a channel, and return it when it is available. See #link: newchannel# for an example. #### ischannelempty Check if a channel is empty and if `readchannel` will block on it. Returns a boolean. #### newref Create a new mutable reference with with initial value set to the argument. #### readref Get the current value of the mutable reference. #### writeref Write a new value to the mutable reference. #### modifyref Atomically modify a reference using a callback. Example: Increment a mutable reference in three threads. ``` proc thread1(ref) for i = 1 to 10000 modifyref(ref, fn (n) (n + 1) endfn) endfor endproc let myref = newref(0) let t1 = startthread(thread1, myref) let t2 = startthread(thread1, myref) let t3 = startthread(thread1, myref) await(t1) await(t2) await(t3) println(readref(myref)) ``` This program should print 30000 as the final value of the ref every time it is run. Try replacing modifyref call with readref/writeref calls and see how the result is sometimes less than 30000.