# How to implement parallel-or?

**URL:** <https://racket.discourse.group/t/how-to-implement-parallel-or/3987>\
**Category:** Questions & Answers\
**Tags:** question, parallelism, futures\
**Created:** [October 27, 2025, 3:29pm UTC](https://racket.discourse.group/t/how-to-implement-parallel-or/3987 "2025-10-27T15:29:09Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [October 27, 2025, 4:57pm UTC](https://racket.discourse.group/t/how-to-implement-parallel-or/3987/2 "2025-10-27T16:57:23Z")

</div>

This is difficult to do with futures, because futures can potentially block, making no more parallel progress until `touch`ed, and there is no mechanism analogous to `choice-evt` to select whichever future is ready first.

But the new parallel threads coming in Racket 9.0 (test a candidate from [https://pre-release.racket-lang.org](https://pre-release.racket-lang.org)!) will make `parallel-or` very convenient to express:

```scheme
#lang racket

(module+ main
  (parallel-or (begin (println 'a) 'a)
               (begin (println 'b) 'b)))

(define-syntax-rule (parallel-or a-expr b-expr)
  (do-parallel-or (λ () a-expr) (λ () b-expr)))

(define (do-parallel-or a-thunk b-thunk)
  (define (spawn thunk)
    (define cust (make-custodian))
    (values (parameterize ([current-custodian cust])
              (thread #:pool 'own #:keep 'results thunk))
            cust))
  (define-values [a-thd a-cust]
    (spawn a-thunk))
  (define-values [b-thd b-cust]
    (spawn b-thunk))
  (define ready-thd
    (sync a-thd b-thd))
  (cond
    [(thread-wait ready-thd)
     => (λ (rslt)
          (custodian-shutdown-all (if (equal? ready-thd a-thd)
                                      b-cust
                                      a-cust))
          rslt)]
    [else
     (define-values [ready-cust other-thd other-cust]
       (if (equal? ready-thd a-thd)
           (values a-cust b-thd b-cust)
           (values b-cust a-thd a-cust)))
     (custodian-shutdown-all ready-cust)
     (cond
       [(thread-wait other-thd)]
       [else
        (custodian-shutdown-all other-cust)
        #f])]))

```

The dance with custodians is intended to arrange that a computation that either returns `#f` or is not chosen has all its resources cleaned up, but also to _not_ shut down any resources from a computation that _is_ chosen, since it might be useful to have `parallel-or` return a custodian-managed resource.

This implementation doesn't consider potential exceptions coming from one (or both) of the parallel computations. You could configure the threads' initial exception handlers to communicate exceptions, or further enhancements to `thread` (and/or integrating the new features into `delay/thread`) might make things more convenient:

> [@Help test via snapshots: parallel threads](https://racket.discourse.group/t/help-test-via-snapshots-parallel-threads/3920/23):
>
> > [@Help test via snapshots: parallel threads](https://racket.discourse.group/t/help-test-via-snapshots-parallel-threads/3920/22):
> >
> > Potentially a `#:keep 'result/exn` option could be added later.
> 
> Yes, I agree. I intended to add that, but haven't gotten to it.

---

_[View the full topic](https://racket.discourse.group/t/how-to-implement-parallel-or/3987)._
