spade-0.1.0.10: docs/functions/concurrency.md
### 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.
Mutable references might appear to serve the same purpose as global variables
but differ in an important way. Modification made to a global variable from a
thread will not be visible from other threads. So if you want to make that
happen, you ll have to use a mutable reference that is shared between the
threads.
#### 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.