Because it bugs me to clone the vector.
Maybe silly, I admit, since cycle recovery
is not the hot path.
But by that same token, we now spend only 1 word
for a null pointer instead of 4 words for a (usually empty) vector.
Currently, when one thread blocks on another, we clone the
stack from that task. This results in a lot of clones, but it also
means that we can't mark all the frames involved in a cycle atomically.
Instead, when we propagate information between threads, we also
propagate the participants of the cycle and so forth.
This branch *moves* the stack into the runtime while a thread
is blocked, and then moves it back out when the thread resumes.
This permits the runtime to mark all the cycle participants at once.
It also avoids cloning.
Instead of creating a future for each edge
in the graph, we now have all dependent queries
block in the runtime and wake up whenever results
are published to see if their results are ready.
We could certainly allocate a CondVar for each dependent
query if we found that spurious wakeups were a problem.
I consider this highly unlikely in practice.
Rather than checking return value of from `Q::cycle_fallback`, we
now consult the computed recovery strategy to decide whether to
panic or to recover. We can thus assume that we will successfully
recover and don't need to check for `None` results anymore.
268: Expose proc macro docs via the main crate r=nikomatsakis a=1tgr
Improve visibility by placing the `database` and `query_group` proc macros at the bottom of the main docs page, instead of manually browsing to the docs for the `salsa-macros` crate.
Co-authored-by: Tim Robinson <tim.g.robinson@gmail.com>
The primary motivation here is reducing dependencies. rand has quite a
few of them, and many come from `getrandom` crate (bindings to system
APIs to get true randomness). Some of `getrandom` crates don't have
Apache 2.0 OR MIT license, and it probably doesn't make sense to make
salsa's licensing situation more complicated for feature we don't even
use.
There's a number of small&fast random crates there:
* randomize
* oorandom
* fastrand
I've picked oorandom because it was the simplest & smallest (doesn't
have a thread_local RNG, for example).
This had two unexpected consequences, one unfortunate, one "medium":
* All `salsa::Database` must be `'static`. This falls out from
`Q::DynDb` not having access to any lifetimes, but also the defaulting
rules for `dyn QueryGroup` that make it `dyn QueryGroup + 'static`. We
don't really support generic databases anyway yet so this isn't a big
deal, and we can add workarounds later (ideally via GATs).
* It is now statically impossible to invoke `snapshot` from a query,
and so we don't need to test that it panics. This is because the
signature of `snapshot` returns a `Snapshot<Self>` and that is not
accessible to a `dyn QueryGroup` type. Similarly, invoking
`Runtime::snapshot` directly is not possible becaues it is
crate-private. So I removed the test. This seems ok, but eventually I
would like to expose ways for queries to do parallel
execution (matklad and I had talked about a "speculation" primitive
for enabling that).
* This commit is 99% boilerplate I did with search-and-replace. I also
rolled in a few other changes I might have preferred to factor out,
most notably removing the `GetQueryTable` plumbing trait in favor of
free-methods, but it was awkward to factor them out and get all the
generics right (so much simpler in this version).
rust-analyzer fails in rust-lang/rust repo on the power target,
because it doesn't have `AtomicU64`. So, lets just use `AtomicUsize`
as a revision number.
Semantically this is wrong, as we are not using revision to address
arrays, but, practically, it's a nice compromise to build on targets
without AtomicU64 and to have large revision numbers on most relevant
targets.
cargo llvm-lines shows that some amount of llvm lines is spend on
`std::mpsc`. Given that this is not the most loved standard library
module, and that our usage of mpsc is extremely limited, it seems
worth-while to implement oneshot channel using parking_lot.
This was an oversight before -- the current type implies that
one introduce a synthetic write (and hence a new revision) from
a `Frozen<DB>`! Not cool.