Place channels are asynchronous, not syncronous (i.e. you don't have
two-way rendez-vous). So the call to put returns immediately in
`loopback-p` before the other end receives the result. And now the
next iteration of the loop's get is in parallel to the put from the
previous iteration's.

A standard way to work with this is to send a channel over in the
first communication and then the communication that's specific to that
initial request happens on that channel. The precise way you set this
up depends on what invariants of the communication you want. Like, you
can create a new thread and just do all the communication there, or
you can keep a list of in-progress communications (in some struct that
holds the channel you're communicating on plus details of the current
state of that "conversation") and then have a big sync that collects
all of the relevant ways in which some communication might make
progress and then uses handle-evt with handlers that loop back after
updating the details of the specific communication that has moved
forward. (This second kind of structure (with the big `sync` and
`handle-evt`) really showcases the beauty of CML, which is where
Racket's evt system comes from (intellectually). It's really amazing
how looking at these kinds of communication in that way can make it
easy to get lots of concurrency and never have race conditions or
other such badness.)

hth,
Robby

On Sat, Jun 15, 2019 at 10:19 AM Matthew Butterick <m...@mbtype.com> wrote:
>
>
> On Jun 14, 2019, at 8:15 PM, Matthew Butterick <m...@mbtype.com> wrote:
>
> But even after approving a lock request from a certain rendering place, the 
> lock server would end up with repeat lock requests from there.
>
>
>
> BTW here's a minimal example showing the puzzling message-garbling behavior 
> between places.
>
> Here, instead of a lock server, I just have a loopback server. What I expect 
> is that each worker sends a request number, and the loopback immediately 
> echoes this number back as a response, so the numbers will always match.
>
> But that's not what happens. At first, the response numbers match the 
> requests. But then they start coming back mismatched. The error rate 
> increases as the `sleep` value decreases, for instance:
>
> worker request 1:46 got response 1:46
> worker request 0:90 got response 0:90
> worker request 0:91 got response 2:31 ### fail
> worker request 2:31 got response 0:91 ### fail
> worker request 7:12 got response 7:12
> worker request 1:47 got response 1:47
> worker request 4:19 got response 0:92 ### fail
> worker request 0:92 got response 4:19 ### fail
> worker request 5:16 got response 5:16
> worker request 0:93 got response 0:93
>
> The garbling happens in a predictable way: every request is answered, but a 
> closely occurring set of requests and responses will be mismatched among 
> themselves. By adjusting the `sleep` value, it's easy to create a flow rate 
> of messages where almost all of them are garbled.
>
>
>
> #lang racket
> (provide main)
>
> (define (main)
>   (define loopback-p
>     (place ch
>            (let loop ()
>              (place-channel-put ch (place-channel-get ch))
>              (loop))))
>
>   (define worker-ps
>     (for/list ([i (in-range (processor-count))])
>       (place ch
>              (match-define (list loopback-p wpidx) (place-channel-get ch))
>              (let make-request ([count 1])
>                (match-define (list wpidxout countout)
>                  (place-channel-put/get loopback-p (list wpidx count)))
>                (displayln (format "worker request ~a:~a got response ~a:~a ~a"
>                                   wpidx count wpidxout countout
>                                   (if (and (eq? wpidx wpidxout) (eq? count 
> countout)) "" "### fail")))
>                (sleep (* 0.01 (add1 wpidx))) ; multiplier makes workers go at 
> different speeds
>                (make-request (add1 count))))))
>
>   (for ([(wp wpidx) (in-indexed worker-ps)])
>     (place-channel-put wp (list loopback-p wpidx)))
>   (map place-wait worker-ps))
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/1A3D2E52-1DDA-40FC-B8F7-816B6E9EFF70%40mbtype.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAL3TdOPEh5Xo6rD%2BHurJbuPGt0pgjW-Mtd%3DWcs2RTN2_1gt%3Dyw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to