Trait salsa_2022::database::ParallelDatabase
source · [−]Expand description
Indicates a database that also supports parallel query
evaluation. All of Salsa’s base query support is capable of
parallel execution, but for it to work, your query key/value types
must also be Send
, as must any additional data in your database.
Required Methods
sourcefn snapshot(&self) -> Snapshot<Self>
fn snapshot(&self) -> Snapshot<Self>
Creates a second handle to the database that holds the
database fixed at a particular revision. So long as this
“frozen” handle exists, any attempt to set
an input will
block.
This is the method you are meant to use most of the time in a
parallel setting where modifications may arise asynchronously
(e.g., a language server). In this context, it is common to
wish to “fork off” a snapshot of the database performing some
series of queries in parallel and arranging the results. Using
this method for that purpose ensures that those queries will
see a consistent view of the database (it is also advisable
for those queries to use the [Runtime::unwind_if_cancelled
]
method to check for cancellation).
Panics
It is not permitted to create a snapshot from inside of a query. Attepting to do so will panic.
Deadlock warning
The intended pattern for snapshots is that, once created, they
are sent to another thread and used from there. As such, the
snapshot
acquires a “read lock” on the database –
therefore, so long as the snapshot
is not dropped, any
attempt to set
a value in the database will block. If the
snapshot
is owned by the same thread that is attempting to
set
, this will cause a problem.
How to implement this
Typically, this method will create a second copy of your
database type (MyDatabaseType
, in the example below),
cloning over each of the fields from self
into this new
copy. For the field that stores the salsa runtime, you should
use the Runtime::snapshot
method to create a snapshot of the
runtime. Finally, package up the result using Snapshot::new
,
which is a simple wrapper type that only gives &self
access
to the database within (thus preventing the use of methods
that may mutate the inputs):
impl ParallelDatabase for MyDatabaseType {
fn snapshot(&self) -> Snapshot<Self> {
Snapshot::new(
MyDatabaseType {
runtime: self.storage.snapshot(),
other_field: self.other_field.clone(),
}
)
}
}