Stop Thread

Here we've added one last card to on-poke to stop the thread and a little extra to on-agent to print things for demonstrative purposes.

thread-starter.hoon

/+ default-agent, dbug
=* card card:agent:gall
%- agent:dbug
^- agent:gall
|_ =bowl:gall
+* this .
def ~(. (default-agent this %|) bowl)
::
++ on-init on-init:def
++ on-save on-save:def
++ on-load on-load:def
++ on-poke
|= [=mark =vase]
^- (quip card _this)
?+ mark (on-poke:def mark vase)
%noun
?+ q.vase (on-poke:def mark vase)
(pair term term)
=/ tid `@ta`(cat 3 'thread_' (scot %uv (sham eny.bowl)))
=/ ta-now `@ta`(scot %da now.bowl)
=/ start-args [~ `tid byk.bowl(r da+now.bowl) p.q.vase !>(q.q.vase)]
:_ this
:~
[%pass /thread/[ta-now] %agent [our.bowl %spider] %watch /thread-result/[tid]]
[%pass /thread/[ta-now] %agent [our.bowl %spider] %poke %spider-start !>(start-args)]
[%pass /thread/updates/[ta-now] %agent [our.bowl %spider] %watch /thread/[tid]/updates]
[%pass /thread-stop/[ta-now] %agent [our.bowl %spider] %poke %spider-stop !>([tid %.y])]
==
==
==
++ on-watch on-watch:def
++ on-leave on-leave:def
++ on-peek on-peek:def
++ on-agent
|= [=wire =sign:agent:gall]
^- (quip card _this)
?+ -.wire (on-agent:def wire sign)
%thread
?+ -.sign (on-agent:def wire sign)
%poke-ack
?~ p.sign
%- (slog leaf+"Thread started successfully" ~)
`this
%- (slog leaf+"Thread failed to start" u.p.sign)
`this
::
%fact
?+ p.cage.sign (on-agent:def wire sign)
%thread-fail
=/ err !< (pair term tang) q.cage.sign
%- (slog leaf+"Thread failed: {(trip p.err)}" q.err)
`this
%thread-done
?: =(*vase q.cage.sign)
%- (slog leaf+"Thread cancelled nicely" ~)
`this
=/ res (trip !<(term q.cage.sign))
%- (slog leaf+"Result: {res}" ~)
`this
%update
=/ msg !< tape q.cage.sign
%- (slog leaf+msg ~)
`this
==
==
%thread-stop
?+ -.sign (on-agent:def wire sign)
%poke-ack
?~ p.sign
%- (slog leaf+"Thread cancelled successfully" ~)
`this
%- (slog leaf+"Thread failed to stop" u.p.sign)
`this
==
==
++ on-arvo on-arvo:def
++ on-fail on-fail:def
--

We've also added a sleep to the thread to keep it running for demonstration.

test-thread.hoon

/- spider
/+ *strandio
=, strand=strand:spider
^- thread:spider
|= arg=vase
=/ m (strand ,vase)
^- form:m
;< =path bind:m take-watch
;< ~ bind:m (send-raw-card [%give %fact ~[path] %update !>("message 1")])
;< ~ bind:m %- send-raw-cards
:~ [%give %fact ~[path] %update !>("message 2")]
[%give %fact ~[path] %update !>("message 3")]
[%give %fact ~[path] %update !>("message 4")]
==
;< ~ bind:m (send-raw-card [%give %kick ~[path] ~])
;< ~ bind:m (sleep ~m1)
|= strand-input:strand
?+ q.arg [~ %fail %not-foo ~]
%foo
[~ %done arg]
==

Save these, |commit, and run with :thread-starter [%test-thread %foo]. You should see:

Thread started successfully
message 1
message 2
message 3
message 4
Thread cancelled successfully
Thread cancelled nicely

Now, try changing the vase in our new card from !>([tid %.y]) to !>([tid %.n]). Save, |commit, and run again. You should see:

Thread started successfully
message 1
message 2
message 3
message 4
Thread cancelled successfully
Thread failed: cancelled

Analysis

The card we've added to our agent:

[%pass /thread-stop/[ta-now] %agent [our.bowl %spider] %poke %spider-stop !>([tid %.y])]

...pokes spider with mark %spider-stop and a vase containing the tid of the thread we want to stop and a ?. The ? specifies whether to end it nicely or not. If %.y it will end with %thread-done and a *vase bunted vase. If %.n it will end with %thread-fail and a vase containing [term tang] where term is %cancelled and tang is ~. You can see the difference in our tests above.