In the case that the current time equals exactly the timeout of
a `sync/timeout`, the Racket process could get stuck (using no CPU)
instead of continuing as it should.
How did we not find this before? Why am I suddenly able to replicate
the problem (i.e., hitting exactly the target timeout in the secheduler
at the millisecond granularity)?
Merge to v6.1
For example, if you accidentally type `raco pkg install` in your
"racket" directory, you'd rather have an error rather than competing
module paths that reach all libraries.
This change requires a coordinated change to the snip-lib pkg and to
the gui-lib package. The docs are in the gui-doc pkg and yet point to
the snip-pkg as the containing pkg, so I updated the version number
for snip-lib and left the version number for gui-lib alone
The `(or/c evt? any/c)` result contract is, of course, equivalent to
`any/c`, but the verbose variant hopefully helps explain that `evt?`
is really expected.
Yes, it would be better if the result contract actually was `evt?`
(and I implemented `replace-evt` that way before re-reading the
`guard-evt` docs).
A test tries to fill a TCP output stream so that it's no longer ready
for writing. There's no real guarantee that it's possible to setup up
and detect that situation, and a failure or two is not too suspicious,
but it really should be possible to fill the buffer. Trying 5 times
should make failure of the test especially unlikely in practice.
The workaround for the way that `test-begin` fails to compose
would drop a lot of information about the test failure. Allow
RackUnit's default printer to show that information but then
also abort.
(My more concrete goal is to understand why a particular test
sometimes fails on DrDr.)
As suggested by Jan Dvořák.
The event created by `replace-evt` is a kind of event-gated
version of `guard-evt`. In particular,
(guard-evt thunk)
could be expressed as
(replace-evt always-evt (lambda (_) (thunk)))
Use `replace-evt` as a shortcut for the case when you want to
synchronize on either A or C, but you need to wait for B to get C.
You could wait on A+B and then, if B is selected, wait on A+C;
wrapping B with `replace-evt` to generate C is a kind of shortcut that
is eaiser to write and avoids tear-down and re-setup of A.
The `replace-evt` constructor is more than a shortcut in the sense
that it builds the pattern A+B->A+C into `sync`, which enables
abstractions that need a B->C transition. So, `replace-evt` adds
expressiveness, but (perhap reassuringly) it does not add any new
rendezvous capability.
Naturally, the procedure given to `replace-evt` can produce
another `replace-evt`, and the event argument to
`replace-evt` could also be a `replace-evt`.
optional and add a contract that calls the 'draw' argument to make
sure it restores the dc state.
The call to the 'draw' function happens right when 'dc' is called and
it tests the property that 'draw' doesn't abuse the state only that
one time and only with x=0 and y=0. This seems likely to catch common
errors, however, since the mismanagement of the state is unlikely to
be related to the values of 'x' and 'y' and also unlikely to depend on
the timing of the the call (i.e., if it happens at all, it probably
always happens).
Another way we could enforce this contract would be to wrap the `draw'
argument so that each time it is called, we grab the state of the dc
and compare it to afterwards. The current strategy is less expensive
and also catches errors earlier (in the case of slidehow specifically,
we'll get the errors during the startup of the presentation instead of
when we try to render a slide (in the middle of the presentation,
typically)).
This change slows down calls to 'dc'. For example, this program:
#lang racket/gui
(require pict)
(define brush (send the-brush-list find-or-create-brush "black" 'solid))
(define (circ w h)
(dc (λ (dc dx dy)
(define orig-pen (send dc get-pen))
(define orig-brush (send dc get-brush))
(send dc set-pen "black" 1 'transparent)
(send dc set-brush brush)
(send dc draw-ellipse dx dy w h)
(send dc set-pen orig-pen)
(send dc set-brush orig-brush))
w h))
(void
(time
(for/fold ([b (blank)]) ([i (in-range 10000)])
(vc-append (circ (random 1000)
(random 1000))
b))))
goes from
cpu time: 16 real time: 17 gc time: 0
to
cpu time: 2166 real time: 2172 gc time: 224
on my machine.
Still, that cost, when measured in a per-call-to-dc way is
only .21 msecs, which seems reasonable given the pain of
tracking down the kinds of bugs that this contract
helps detect.
Include documentation that was part of the installer, because a package catalog
may want to show documentation links independent of whether the package
was included in a distribution.