# Events and concurrency

**URL:** <https://racket.discourse.group/t/events-and-concurrency/1021>\
**Category:** Questions & Answers\
**Tags:** question\
**Created:** [May 24, 2022, 3:48pm UTC](https://racket.discourse.group/t/events-and-concurrency/1021 "2022-05-24T15:48:20Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![edoput](https://avatars.discourse-cdn.com/v4/letter/e/aeb1de/32.png) [@edoput](https://racket.discourse.group/u/edoput)\
**Post date:** [May 24, 2022, 3:48pm UTC](https://racket.discourse.group/t/events-and-concurrency/1021/1 "2022-05-24T15:48:20Z")

</div>

When looking at the [events reference page](https://docs.racket-lang.org/reference/sync.html) I saw that there are a number of procedures that are very similar. While the difference between `wrap-evt` and `handle-evt` is understandable and I can see the use cases for both I'm having a hard time finding use cases (and relative differences) between `guard-evt`, `nack-guard-evt` and `poll-guard-evt`.

I think I can implement cancellation using `nack-guard-evt`. As an example I can try and fetch a resource from different servers concurrently by spawning competing threads inside a `nack-guard-evt`.

```scheme
(sync
    ;; spawn the first thread 
    (nack-guard-evt (lambda (nack)
                            (thread (lambda ()
                                            (sync
                                                 nack ;; we got cancelled, cleanup any resource we may have allocated
                                                 ...)))))
   ;; spawn the competition

```

Now the first thread that returns an event will be selected and the rest will receive a "negative acknowledgment" so they can stop doing any work.

In `poll-guard-evt` it's not clear what the difference between polling and blocking synchronization is. Is it related to `sync` and `sync/timeout`?

In `guard-evt` the explicit difference with `wrap-evt` and `handle-evt` is that the `maker` procedure can only be called at most once per `sync` call. I really have no idea how this can be used but I'm thinking it may be useful if the `maker` procedure is expensive.

Moreover in what cases can `sync` call an event generator procedure more than once? My understanding is that `sync` loops over the events I give it and waits for an event to be ready. This means each expression I put in my sync will be evaluated to an event but it's not clear now if each loop evals the expressions from scratch and more than one time.

---

<div class="post-metadata">

**Author:** ![ryanc](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/ryanc/32/71_2.png) [@ryanc](https://racket.discourse.group/u/ryanc)\
**Post date:** [May 24, 2022, 6:09pm UTC](https://racket.discourse.group/t/events-and-concurrency/1021/2 "2022-05-24T18:09:10Z")

</div>

> [@edoput](#):
>
> I think I can implement cancellation using `nack-guard-evt`.

Yes, `nack-guard-evt` is to implement request cancellation. There is an example in the paper "Kill-Safe Synchronization Abstractions".

> [@edoput](#):
>
> In `poll-guard-evt` it's not clear what the difference between polling and blocking synchronization is. Is it related to `sync` and `sync/timeout`?

It seems that a call to `sync/timeout` with a timeout of zero or a procedure is considered a "poll" and anything else is considered "blocking". Source: In /racket/src/thread/sync, the `sync-poll` function calls a `poll-guard-evt`'s maker with the value of `just-poll?`; that argument is determined by the calls from `do-sync`.

> [@edoput](#):
>
> In `guard-evt` the explicit difference with `wrap-evt` and `handle-evt` is that the `maker` procedure can only be called at most once per `sync` call. I really have no idea how this can be used but I'm thinking it may be useful if the `maker` procedure is expensive.

I'm confused, because you seem to be talking about two unrelated things here. Can you clarify?

> [@edoput](#):
>
> Moreover in what cases can `sync` call an event generator procedure more than once? My understanding is that `sync` loops over the events I give it and waits for an event to be ready. This means each expression I put in my sync will be evaluated to an event but it's not clear now if each loop evals the expressions from scratch and more than one time.

First, `sync` is a procedure, so its argument _expressions_ are always evaluated eagerly and in order, just like for any other procedure. Some event values, like instances of `guard-evt`, represent explicitly delayed computation of the "real" event(s) that you want to synchronize on. These delayed events are forced in a pseudo-random order. I believe that when a delayed event is forced, it is replaced in the `sync` call's current list of candidates with the new event(s) that it produces, so it generally won't get forced multiple times. (Except if there are duplicates in the original list, or in strange cases like a `guard-evt` instance whose maker just returns the same `guard-evt` instance.)

---

<div class="post-metadata">

**Author:** ![edoput](https://avatars.discourse-cdn.com/v4/letter/e/aeb1de/32.png) [@edoput](https://racket.discourse.group/u/edoput)\
**Post date:** [May 25, 2022, 7:28am UTC](https://racket.discourse.group/t/events-and-concurrency/1021/3 "2022-05-25T07:28:05Z")

</div>

> I'm confused, because you seem to be talking about two unrelated things here. Can you clarify?

All the procedures `*-evt` procedures take an event as an argument except for `guard-evt`. If I have a event generating procedure `my-evt` I can also use it with all `*-evt` procedures but with `guard-evt` I don't have to call it right now. In `(wrap-evt (my-evt) ...)` `my-evt` is evaluated before `sync` and in `(guard-evt my-evt)` instead it is evaluated after `sync` has started the loop?

Still I'm confused by the words " The maker procedure may be called by sync at most once for a given call to sync". If I were to pass to sync the event `(my-evt)` the `my-evt` it is evaluated once and wrapping it in `(guard-evt (my-evt))` may evaluate it at most once. When would I want to use this?

---

<div class="post-metadata">

**Author:** ![ryanc](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/ryanc/32/71_2.png) [@ryanc](https://racket.discourse.group/u/ryanc)\
**Post date:** [May 25, 2022, 11:20am UTC](https://racket.discourse.group/t/events-and-concurrency/1021/4 "2022-05-25T11:20:59Z")

</div>

The main purpose of `guard-evt` is to create an event that depends on the state when the `sync` call begins. For example, if `sync/timeout` were not available, you could implement something similar with the following:

```scheme
;; sleep-evt : Real -> Evt
(define (sleep-evt seconds)
  (guard-evt
    (lambda ()
      (alarm-evt (+ (current-inexact-milliseconds) (* 1000.0 seconds))))))

;; sleep-10s-evt : Evt
(define sleep-10s-evt (sleep-evt 10))

```

Here, `sleep-10s-evt` can be defined once and used many times to implement a 10 second timeout. Because of the `guard-evt` wrapper, each time it is used in a `sync` call, it (potentially) creates a fresh primitive `alarm-evt`. If you deleted the `guard-evt` wrapper, it would time out 10 seconds from the definition of `sleep-10s-evt`, and after that time passed it would be equivalent to `always-evt`.

Another common pattern is to use `guard-evt` to read state from variables. In that case the variables should only be accessible by the thread `sync`ing on the guard event; otherwise you can get races.

---

<div class="post-metadata">

**Author:** ![edoput](https://avatars.discourse-cdn.com/v4/letter/e/aeb1de/32.png) [@edoput](https://racket.discourse.group/u/edoput)\
**Post date:** [May 25, 2022, 5:50pm UTC](https://racket.discourse.group/t/events-and-concurrency/1021/5 "2022-05-25T17:50:32Z")

</div>

Thanks so much for all the help and the pointer to the "Kill-Safe Synchronization Abstractions" paper.
