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?: =(q.cage.sign *vase)%- (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 successfullymessage 1message 2message 3message 4Thread cancelled successfullyThread 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 successfullymessage 1message 2message 3message 4Thread cancelled successfullyThread 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.