@@ -5,8 +5,7 @@ template = "doc.html"
55aliases = ["/docs/learn/arvo/gall/"]
66+++
77
8−This document describes Gall, the Arvo userspace vane. It is split into two main
9−sections: Agents and [Threads](#threads).
8+This document describes Gall, the Arvo userspace vane.
109
1110# Agents
1211
@@ -15,7 +14,7 @@ Urbit code lives in the following basic categories:
1514- Runtime (Nock interpreter, persistence engine, IO drivers, jets)
1615- Kernel vanes (managed by Arvo)
1716- Userspace agents (managed by Gall, permanent state)
18−- Userspace imps (managed by Spider, transient state)
17+- Userspace threads (managed by Spider, transient state)
1918
2019This lays out the framework for the third category: Agents.
2120
@@ -558,237 +557,3 @@ If an error happens in `+on-poke`, the crash report goes into the
558557`+on-subscription`, the crash report goes into the `%watch-ack`
559558response. If a crash happens in any of the other handlers, the report
560559is passed into this arm.
561−
562−
563−# Threads
564−
565−As discussed in [Agents](#agents), Urbit code lives in the following basic
566−categories:
567−
568−- Runtime (Nock interpreter, persistence engine, IO drivers, jets)
569−- Kernel vanes (managed by Arvo)
570−- Userspace agents (managed by Gall, permanent state)
571−- Userspace threads (managed by Spider, transient state)
572−
573−This describes the last category: Threads.
574−
575−A thread is a monadic function that takes arguments and produces a
576−result. It may perform input and output while running, so it is not a
577−pure function. It may fail.
578−
579−An agent's strength is that it's permanent and bulletproof. All state
580−transitions are defined, and each action it performs is a transaction.
581−Code upgrades preserve existing state.
582−
583−An agent's weakness is complex input and output. Since each state
584−transition must be explicitly handled, the complexity of an agent
585−explodes with the amount of IO it handles. At best, this results in
586−long and complex code; at worst, unexpected states are mishandled,
587−corrupting permanent state.
588−
589−A thread's strength is that it can easily perform complex IO operations.
590−It uses what's often called the IO monad (plus the exception monad) to
591−provide a natural framework for IO.
592−
593−A thread's weakness is that it's impermanent and may fail unexpectedly.
594−In most of its intermediate states, it expects only a small number of
595−events (usually one), so if it receives anything it didn't expect, it
596−fails. When code is upgraded, it's impossible to upgrade a running
597−thread, so it fails.
598−
599−Thus, for anything that needs to be permament, use an agent. When you
600−need to do a long or complex sequence of IO operations, reduce that to a
601−single logical IO operation by spinning it out into a thread. If you
602−only change your agent's state in response to success of the thread, an
603−IO failure will never result in partially applied state changes.
604−
605−A thread may also be run from the dojo by prefixing its name with `-`
606−and giving it any arguments it requires. If alone, any result will be
607−printed to the screen; else the output may be piped into an agent or
608−other sinks.
609−
610−## Specification
611−
612−```hoon
613−+$ thread $-(vase _*form:(strand ,vase))
614−```
615−
616−A thread is a running strand. It receives an argument as a vase and may
617−prodduce a vase of a result.
618−
619−```hoon
620−+$ tid @tasession
621−+$ start-args
622− [parent=(unit tid) use=(unit tid) file=term =vase]
623−```
624−
625−To run a thread, poke Spider with mark `%spider-start` and a value of
626−type `start-args`. `parent` is an optional parent, `use` is an optional
627−id, `file` is the filename, and `vase` is the argument. If the parent
628−is specified (usually to the thread that spawned this thread), then
629−when the parent ends, the child will end too.
630−
631−A thread may succeed or fail. You may recieve the return value or be
632−notified of failure by subscribing to Spider at `/thread-result/[tid]`,
633−where `tid` is the same one you passed in `use`. Take care to create a
634−`tid` that will be unique from any other that may be created, for
635−example with:
636−
637−```hoon
638−(scot %ta (cat 3 'my-agent_' (scot %uv (sham eny))))`
639−```
640−
641−The `%fact` that comes back on this subscription will have mark either
642−`%thread-fail` or `%thread-done`. If it failed, the content will have
643−type `[term tang]` with an explanation of the error. If it succeeded,
644−the content will be whatever the thread produced.
645−
646−```hoon
647−+$ input [=tid =cage]
648−```
649−
650−You may poke a thread by poking Spider with `%spider-input`. `tid` is
651−the id of the thread you wish to poke, and `cage` is the data to poke it
652−with.
653−
654−You may subscribe to a thread by subscribing to Spider at
655−`/thread/[tid]/path`.
656−
657−You may stop a thread by poking Spider with `%spider-stop` and data
658−`[tid ?]`, where `tid` is the thread you wish to stop and the loobean
659−decides whether to quit nicely (suppresses printfs).
660−
661−## Writing threads
662−
663−A thread is just a function from a vase of arguments to a strand that
664−produces a vase of the result. We say "just" not because it's obvious
665−yet what that means but because it means we only need to explain how to
666−write strands, and threads are just a particular case.
667−
668−The type of a strand is defined in lib/strand, but you will rarely touch
669−those types directly. Most of the time, you will use two functions
670−`pure` and `bind` combined with any of the functions defined in
671−lib/strandio.
672−
673−### Strand fundamentals
674−
675−When writing strands, you almost always want to start by specializing
676−`strand` to your return type. A strand can produce any type, but you
677−must specify up front what type it will produce. By convention, we use
678−the variable `m` for this. For example, if you are going to produce a
679−`@ud`, use:
680−
681−```hoon
682−=/ m (strand ,@ud)
683−^- form:m
684−...
685−```
686−
687−Note that `m` is a core that has three arms:
688−
689−`+form` is the mold of the strand, suitable for `^-`.
690−
691−`+pure` produces a strand that does nothing except return a value. So,
692−`(pure:(strand ,@tas) %foo)` is a strand that produces `%foo` without
693−doing any IO. Thus, the most trivial thread is:
694−
695−```hoon
696−/- spider
697−/+ strandio
698−=, strand=strand:spider
699−^- thread:spider
700−|= vase
701−=/ m (strand ,vase)
702−^- form:m
703−(pure:m *vase)
704−```
705−
706−`+bind`, used with `;<`, takes two strands and runs one after the other,
707−letting you use the result of the first strand in the second. For
708−example:
709−
710−```hoon
711−;< num=@ud bind:m (pure:m 5)
712−(pure:m +(num))
713−```
714−
715−Has the same result as:
716−
717−```hoon
718−(pure:m 6)
719−```
720−
721−### Other useful functions
722−
723−There are many useful strand functions in lib/strandio and some other
724−libraries. For example:
725−
726−`+sleep` waits for the specified time.
727−
728−`+get-time` gets the current time.
729−
730−`+poke` pokes an agent.
731−
732−`+watch` subscribes to an agent.
733−
734−`+fetch-json` produces the JSON at a particular URL.
735−
736−`+retry` tries a strand repeatedly with exponential backoff until it
737−succeeeds.
738−
739−`+start-thread` starts another thread.
740−
741−`send-raw-card` sends any card.
742−
743−## Examples
744−
745−```hoon
746−/- spider
747−/+ strandio
748−=, strand=strand:spider
749−^- thread:spider
750−|= arg=vase
751−=/ m (strand ,vase)
752−^- form:m
753−=+ !<([arg=@dr ~] arg)
754−;< now-1=@da bind:m get-time:strandio
755−;< ~ bind:m (sleep:strandio arg)
756−;< now-2=@da bind:m get-time:strandio
757−(pure:m !>(`@dr`(sub now-2 now-1)))
758−```
759−
760−The first seven lines are the same boilerplate we saw before. After
761−that, it `!<`'s the argument to its expected type. It saves the current
762−time in `now-1`, sleeps how long the argument says to, then gets the
763−time again and produces the difference between the two times. This
764−number should be close to the argument you passed in, plus a little for
765−computation time. You can run this at the dojo with `-time ~s1`.
766−
767−```hoon
768−/- spider
769−/+ *ph-io
770−=, strand=strand:spider
771−^- thread:spider
772−|= args=vase
773−=/ m (strand ,vase)
774−;< ~ bind:m start-simple
775−;< ~ bind:m (raw-ship ~bud ~)
776−;< ~ bind:m (dojo ~bud "[%test-result (add 2 3)]")
777−;< ~ bind:m (wait-for-output ~bud "[%test-result 5]")
778−;< ~ bind:m end-simple
779−(pure:m *vase)
780−```
781−
782−This is uses `lib/ph/io` to run a pH test. Aqua and pH are described
783−[elsewhere](@/docs/hoon/guides/aqua.md), but if you've initialized Aqua by running `|start %aqua` and
784−`:aqua +solid`, then you can run `-ph-add` to execute this thread.
785−
786−It starts by running some virtualization initialization with
787−`start-simple`. Then, it boots a guest ship called ~bud, types a line
788−into the dojo, and waits for it to printed the expected output.
789−
790−It's easy to see how this building blocks could be combined to perform
791−complex tests. For example, you could start several ships and have them
792−`|hi` each other, sync from each other, or do anything else. Check out
793−`lib/ph/io` and `lib/ph/azimuth` for other useful functions in constructing
794−pH tests.