packages feed

spade-0.1.0.9: 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.

#### 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.