# Child Thread

Here's a simple example of a thread that starts another thread:

{% code title="/ted/parent.hoon" lineNumbers="true" %}

```hoon
/+  *strandio
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
;<  =tid:rand  bind:m  (start-thread %child)
(pure:m !>(~))
```

{% endcode %}

{% code title="/ted/child.hoon" lineNumbers="true" %}

```hoon
/+  *strandio
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
%-  (slog leaf+"foo" ~)
(pure:m !>(~))
```

{% endcode %}

Save `parent.hoon` and `child.hoon` in `/ted` of the `%base` desk, `|commit %base` and run `-parent`. You should see something like:

```
foo
> -parent
~
```

`parent.hoon` just uses the `strandio` function `+start-thread` to start `child.hoon`, and `child.hoon` just prints `foo` to the dojo. Since we got `foo` we can tell the second thread did, in fact, run.

```hoon
;<  =tid:rand  bind:m  (start-thread %child)
```

See here how we gave `+start-thread` the name of the thread to run. It returns the `$tid` (thread ID) of the thread, which we could then use to poke it or whatever.

`+start-thread` handles creating the `$tid` for the thread so is quite convenient.

Note that threads we start this way will be a child of the thread that started them, and so will be killed when the parent thread ends.

## Start thread and get its result <a href="#start-thread-and-get-its-result" id="start-thread-and-get-its-result"></a>

If we want to actually get the result of the thread we started, it's slightly more complicated. We note that this is mostly the same as `+await-thread:strandio`.

{% code title="/ted/parent.hoon" lineNumbers="true" %}

```
```

{% endcode %}

```hoon
/+  *strandio
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
;<  =bowl:rand  bind:m  get-bowl
=/  tid  `@ta`(cat 3 'strand_' (scot %uv (sham %child eny.bowl)))
;<  ~           bind:m  (watch-our /awaiting/[tid] %spider /thread-result/[tid])
;<  ~           bind:m  %-  poke-our
                        :*  %spider
                            %spider-start
                            !>([`tid.bowl `tid byk.bowl(r da+now.bowl) %child !>(~)])
                        ==
;<  =cage       bind:m  (take-fact /awaiting/[tid])
;<  ~           bind:m  (take-kick /awaiting/[tid])
?+  p.cage  ~|([%strange-thread-result p.cage %child tid] !!)
  %thread-done  (pure:m q.cage)
  %thread-fail  (strand-fail:rand !<([term tang] q.cage))
==
```

{% code title="/ted/child.hoon" lineNumbers="true" %}

```
```

{% endcode %}

```hoon
/+  *strandio
|%
++  url  "https://jsonplaceholder.typicode.com/todos/1"
+$  todo  [user-id=@ud id=@ud title=@t completed=?]
++  decode
  =,  dejs:format
  (ot ['userId' ni] ['id' ni] ['title' so] ['completed' bo] ~)
--
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
;<  =json  bind:m  (fetch-json url)
(pure:m !>(`todo`(decode json)))
```

`child.hoon` simply grabs the JSON response from <https://jsonplaceholder.typicode.com> and converts it to a noun.

`parent.hoon` is a bit more complicated so we'll look at it line-by-line

```hoon
;<  =bowl:rand  bind:m  get-bowl
```

First we grab the bowl

```hoon
=/  tid  `@ta`(cat 3 'strand_' (scot %uv (sham %child eny.bowl)))
```

Then we generate a `$tid` for the thread we're going to start

```hoon
;<  ~  bind:m  (watch-our /awaiting/[tid] %spider /thread-result/[tid])
```

We pre-emptively subscribe for the result. Spider sends the result at `/thread-result/[tid]` so that's where we subscribe.

```hoon
;<  ~  bind:m  %-  poke-our
               :*  %spider
                   %spider-start
                   !>([`tid.bowl `tid byk.bowl(r da+now.bowl) %child !>(~)])
               ==
```

Spider takes a poke with a mark `%spider-start` and a vase containing `[parent=(unit tid) use=(unit tid) =beak file=term =vase]` to start a thread, where:

* `.parent` is an optional parent thread. In this case we say the parent is our tid. Specifying a parent means the child will be killed if the parent ends.
* `.use` is the thread ID for the thread we're creating
* `.beak` is a `[p=ship q=desk r=case]` triple which specifies the desk and revision containing the thread we want to run. In this case we just use `byk.bowl`, but with the date of revision `r` changed to `now.bowl`.
* `.file` is the filename of the thread we want to start
* `.vase` is the vase it will be given as an argument when it's started

```hoon
;<  =cage  bind:m  (take-fact /awaiting/[tid])
```

We wait for a fact which will be the result of the thread.

```hoon
;<  ~  bind:m  (take-kick /awaiting/[tid])
```

Spider will kick us from the subscription when it ends the thread so we also take that kick.

```hoon
?+  p.cage  ~|([%strange-thread-result p.cage %child tid] !!)
  %thread-done  (pure:m q.cage)
  %thread-fail  (strand-fail !<([term tang] q.cage))
==
```

Finally we test whether the thread produced a `%thread-done` or a `%thread-fail`. These are the two possible marks produced by spider when it returns the results of a thread. A `%thread-done` will contain a vase with the result, and a `%thread-fail` will contain an error message and traceback, so we see which it is and then either produce the result with `+pure` or trigger a `%thread-fail` with the error we got from the child.

## Stop a thread <a href="#stop-a-thread" id="stop-a-thread"></a>

{% code title="/ted/parent.hoon" lineNumbers="true" %}

```hoon
/+  *strandio
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
;<  =bowl:rand  bind:m  get-bowl
=/  tid  `@ta`(cat 3 'strand_' (scot %uv (sham %child eny.bowl)))
%-  (slog leaf+"Starting child thread..." ~)
;<  ~           bind:m  %-  poke-our
                        :*  %spider
                            %spider-start
                            !>([`tid.bowl `tid byk.bowl(r da+now.bowl) %child !>(~)])
                        ==
;<  ~           bind:m  (sleep ~s5)
%-  (slog leaf+"Stopping child thread..." ~)
;<  ~           bind:m  %-  poke-our
                        :*  %spider
                            %spider-stop
                            !>([tid %.y])
                        ==
;<  ~           bind:m  (sleep ~s2)
%-  (slog leaf+"Done" ~)
(pure:m !>(~))
```

{% endcode %}

{% code title="/ted/child.hoon" lineNumbers="true" %}

```hoon
/+  *strandio
=>
|%
++  looper
  =/  m  (strand:rand ,~)
  ^-  form:m
  %-  (main-loop ,~)
  :~  |=  ~
      ^-  form:m
      ;<  ~  bind:m  (sleep `@dr`(div ~s1 2))
      %-  (slog leaf+"child thread" ~)
      (pure:m ~)
  ==
--
|=  arg=vase
=/  m  (strand:rand ,vase)
^-  form:m
;<  ~  bind:m  looper
(pure:m !>(~))
```

{% endcode %}

`child.hoon` just prints to the dojo in a loop.

`parent.hoon` starts `child.hoon`, and then pokes Spider like:

```hoon
;<  ~  bind:m  %-  poke-our
               :*  %spider
                   %spider-stop
                   !>([tid %.y])
               ==
```

* `%spider-stop` is the mark that tells Spider to kill a thread.
* `$tid` is the tid of the thread to kill
* `%.y` tells Spider to suppress traceback in the result of the killed thread. If you give it `%.n` it will include the traceback.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.urbit.org/urbit-os/base/threads/examples/child-thread.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
