Mutable `eq?`- and `eqv?`-based hash tables were formerly guarded by a
lock that made them safe for Scheme threads (i.e., OS-level threads).
In particular, that futures could concurrently access hash tables. But
the cost of that lock appears to be too high for such a rarely-used
capability.
Switching `eq?`- and `eqv?`-based hash tables so that they're safe
only for Racket threads means that the lock on a hash table can be
much cheaper. A lock is still needed to because the Rumble layer adds
extra fields for iteration. In the specific case of `hash-ref` on
`eq?`-based tables, however, the lock can be ignored, which makes one
of the most common `hash-ref`s much faster.
Overall, `hash-ref` on a mutable `eq?`-based hash table is now 4-5
times as fast, which makes it about twice as fast as traditional
Racket's `hash-ref`. A `hash-set!` operation is about twice as fast as
before, which puts it on par with traditional Rackets `hash-set!`. The
`hash-ref` improvement makes `send` about twice as fast as before in
Racket CS, making it a little faster than traditional Racket.
Since futures can no longer concurrently access `eq?`- and
`eqv?`-based hash tables, they have to synchronize with the main
thread for access. Racket CS had avoided the "sync" action on futures
that traditional Racket sometimes uses, but this change introduces
sync actions to Racket CS, since it's appropriate for accessing
mutable `eq?`- and `eqv?`-based hash tables.
Adjust the internal engine protocol to avoid a jump from a starting
engine (representing a thread) to a scheduler outside of an engine
to a target engine (for a swapped-ni thread); instead, jump from the
first engine to the target, effectively running the scheduler within
the starting engine's context.
In a file-stream output port or TCP output port, when flushing
encounters an error, consistently discard bytes in the buffer. This
isn't the obviously right choice, but otherwise a future flush attempt
(including one triggered by trying to close the port or one triggered
by a plumber) will likely just fail again, which is probably worse
than dropping bytes.
Also, fix related problems/inconsistencies.
Overall changes:
* For traditional Racket, discard bytes in a TCP port when flushing
fails.
* For Racket CS, discard bytes in file-stream and TCP output ports
when flushing fails.
* For traditional Racket, when a file-stream port flush is
interrupted by an asynchronous break, *don't* discard buffered
bytes.
* For Racket CS, don't register TCP ports with the current plumber.
When the original compiler handler is called with a true second
argument, then the resulting module is not serializable. Improve
detecting and reporting of the misuse.
The error is phrase in terms of linklets, which is not ideal, but
that's the level where the error can be detected. Abusing the original
compile handler in this way is not easy, though, so maybe this
improvement is enough.
Adds an additional line to the error message that is raised when a
required module provides a binding that is already provided by another
required module. The additional line displays the name of the first
module that provides the binding.
The error before this change:
tmp/c.rkt:4:9: module: identifier already required
at: x
in: "b.rkt"
location...:
tmp/c.rkt:4:9
and after:
tmp/c.rkt:4:9: module: identifier already required
at: x
in: "b.rkt"
also provided by: "a.rkt"
location...:
tmp/c.rkt:4:9
Add text of MIT and Apache v2 licenses.
Add initial CONTRIBUTING.md file which specifies contribution license.
Add COPYRIGHT.txt file which specifies the license and lists some
external components.
The LGPL license stays in its current location to avoid having to
modify the build right now.
The Mac OS 10.15 headers include a `#pragma` just before the closing
`;` of a `struct` declaration. That confuses poor xform. Handle this
special case by detecting it and swapping the order of the `#pragma`
and `;`.
Recently GitLab added the needs keyword which allows implementing dag
layouts for pipelines. CI also spends a lot of time building
dependencies. A custom image currently hosted in
https://github.com/pmatos/racket-ci contains the dependencies to build
racket properly.
Enabling both features that cuts CI time by 60%.
Note that we use an empty needs keyword to mean that a job depends on
nothing but it is currently ignored pending a fix for
https://gitlab.com/gitlab-org/gitlab/issues/30631
If a source file name lacks an extension, then the pkg-step would get
confused trying to convert a ".zo" name back to a source name. The
original name is not really needed, anyway.
When a reference to a local variable is updated with the scopes of its
binding in a fully expanded program, remove the syntax-original
property if the original reference had macro-intrudction scopes.
Closes#2820
Trying to be more helpful about the thread running an `unsafe-poller`
callback gets in the way of making the process sleep when multiple
threads are blocked on unsafe pollers.
Closes#2833
Prune some `with-continuation-marks` forms that aren't observable
(because the body is simple enough that it won't inspect marks). More
significantly, specialize `with-continuation-marks` forms to indicate
when the current frame is known to have no marks and to indicate
when tthe key expression is known to produce a non-impersonator.
Since `#%app` (used where an applicable structure might show up)
injects its own `procedure?` test and makes sure that that a procedure
is returned to the function position of the application, use `#3%$app`
to make Chez Scheme suppress a redundant `procedure?` check for the
appliction.
It's not clear that a thread can be descheduled without the current
thread's work counting as progress, but a descheduled thread certainly
shouldn't coun as a no-progress scheduled thread.
Only one instance of each callback is needed. Allowing them to pile up
is inefficient, and possibly it can trigger a reaction that causes
even more to pile up.