X-Git-Url: https://jxself.org/git/?p=8sync.git;a=blobdiff_plain;f=doc%2F8sync-new-manual.org;h=844653fa0b6a3da7eedd30ad376775d65fcc5759;hp=2545b1643e0f1323cc90accf2e5eaec58b790218;hb=61dba76070f6b468dd918e6f8d8791231cf2ba6f;hpb=8a163053ad2008ef8be013224a8fd15b96287bdf diff --git a/doc/8sync-new-manual.org b/doc/8sync-new-manual.org index 2545b16..844653f 100644 --- a/doc/8sync-new-manual.org +++ b/doc/8sync-new-manual.org @@ -409,7 +409,7 @@ and will always yield to the scheduler. Our while loop also checks "actor-alive?" to see whether or not it is still registered. In general, if you keep a loop in your actor that regularly yields -to the scheduler, you should check this. +to the scheduler, you should check this.[fn:actor-alive-deprecated-soon] (An alternate way to handle it would be to not use a while loop at all but simply send a message to ourselves with "<-" to call the sleeper-loop handler again. @@ -646,6 +646,12 @@ manager> Oh! I guess you can go home then. worker> Whew! Free at last. #+END_SRC +[fn:actor-alive-deprecated-soon] + Or rather, for now you should call =actor-alive?= if your code + is looping like this. + In the future, after an actor dies, its coroutines will + automatically be "canceled". + ** Writing our own network-enabled actor So, you want to write a networked actor! @@ -660,7 +666,8 @@ Well, luckily that's pretty easy, especially with all you know so far. (define-actor () ((*init* telcmd-init) (*cleanup* telcmd-cleanup) - (new-client telcmd-new-client)) + (new-client telcmd-new-client) + (handle-line telcmd-handle-line)) (socket #:accessor telcmd-socket #:init-value #f)) #+END_SRC @@ -740,12 +747,12 @@ In our case, we politely close the socket when == dies. (cond ((eof-object? line) (close client)) (else - (telcmd-handle-line telcmd client - (string-trim-right line #\return)) + (<- (actor-id telcmd) 'handle-line + client (string-trim-right line #\return)) (when (actor-alive? telcmd) (loop))))))) - (define (telcmd-handle-line telcmd client line) + (define (telcmd-handle-line telcmd message client line) (match (string-split line #\space) (("") #f) ; ignore empty lines (("time" _ ...) @@ -770,7 +777,7 @@ agenda.[fn:setvbuf] The actual method called whenever we have a "line" of input is pretty straightforward... in fact it looks an awful lot like the IRC bot handle-line procedure we used earlier. -No surprises there! +No surprises there![fn:why-send-a-message-to-handle-line] Now let's run it: @@ -824,6 +831,20 @@ Happy hacking! finishes handling one message. Our loop couldn't look quite like this though! +[fn:why-send-a-message-to-handle-line] + Well, there may be one surprise to the astute observer. + Why are we sending a message to ourselves? + Couldn't we have just dropped the argument of "message" to + telcmd-handle-line and just called it like any other procedure? + Indeed, we /could/ do that, but sending a message to ourself has + an added advantage: if we accidentally "break" the + telcmd-handle-line procedure in some way (say we add a fun new + command we're playing with it), raising an exception won't break + and disconnect the client's main loop, it'll just break the + message handler for that one line, and our telcmd will happily + chug along accepting another command from the user while we try + to figure out what happened to the last one. + ** An intermission: about live hacking This section is optional, but highly recommended.