Skip to content

Instantly share code, notes, and snippets.

@Kixiron
Created July 19, 2020 21:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kixiron/3deb7c73f89cf27ce5dc83c97bd317d3 to your computer and use it in GitHub Desktop.
Save Kixiron/3deb7c73f89cf27ce5dc83c97bd317d3 to your computer and use it in GitHub Desktop.
pub trait StringInterner:
salsa::Database + salsa::plumbing::HasQueryGroup<InternerDatabase> + Database
{
fn intern_string(&self, key0: S) -> IStr;
fn lookup_intern_string(&self, key0: IStr) -> (S);
}
/// Representative struct for the query group.
pub struct InternerDatabase {}
impl salsa::plumbing::QueryGroup for InternerDatabase {
type DynDb = dyn StringInterner;
type GroupStorage = StringInternerGroupStorage__;
}
impl<DB> StringInterner for DB
where
DB: Database,
DB: salsa::Database,
DB: salsa::plumbing::HasQueryGroup<InternerDatabase>,
{
fn intern_string(&self, key0: S) -> IStr {
fn __shim(db: &dyn StringInterner, key0: S) -> IStr {
salsa::plumbing::get_query_table::<InternStringQuery>(db).get((key0))
}
__shim(self, key0)
}
fn lookup_intern_string(&self, key0: IStr) -> (S) {
fn __shim(db: &dyn StringInterner, key0: IStr) -> (S) {
salsa::plumbing::get_query_table::<InternStringLookupQuery>(db).get((key0))
}
__shim(self, key0)
}
}
pub struct InternStringQuery;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::default::Default for InternStringQuery {
#[inline]
fn default() -> InternStringQuery {
InternStringQuery {}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for InternStringQuery {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
InternStringQuery => {
let mut debug_trait_builder = f.debug_tuple("InternStringQuery");
debug_trait_builder.finish()
}
}
}
}
impl InternStringQuery {
/// Get access to extra methods pertaining to this query. For
/// example, you can use this to run the GC (`sweep`) across a
/// single input. You can also use it to invoke this query, though
/// it's more common to use the trait method on the database
/// itself.
pub fn in_db(self, db: &dyn StringInterner) -> salsa::QueryTable<'_, Self> {
salsa::plumbing::get_query_table::<InternStringQuery>(db)
}
}
impl InternStringQuery {
/// Like `in_db`, but gives access to methods for setting the
/// value of an input. Not applicable to derived queries.
///
/// # Threads, cancellation, and blocking
///
/// Mutating the value of a query cannot be done while there are
/// still other queries executing. If you are using your database
/// within a single thread, this is not a problem: you only have
/// `&self` access to the database, but this method requires `&mut
/// self`.
///
/// However, if you have used `snapshot` to create other threads,
/// then attempts to `set` will **block the current thread** until
/// those snapshots are dropped (usually when those threads
/// complete). This also implies that if you create a snapshot but
/// do not send it to another thread, then invoking `set` will
/// deadlock.
///
/// Before blocking, the thread that is attempting to `set` will
/// also set a cancellation flag. In the threads operating on
/// snapshots, you can use the [`is_current_revision_canceled`]
/// method to check for this flag and bring those operations to a
/// close, thus allowing the `set` to succeed. Ignoring this flag
/// may lead to "starvation", meaning that the thread attempting
/// to `set` has to wait a long, long time. =)
///
/// [`is_current_revision_canceled`]: struct.Runtime.html#method.is_current_revision_canceled
pub fn in_db_mut(self, db: &mut dyn StringInterner) -> salsa::QueryTableMut<'_, Self> {
salsa::plumbing::get_query_table_mut::<InternStringQuery>(db)
}
}
impl salsa::Query for InternStringQuery {
type Key = (S);
type Value = IStr;
type Storage = salsa::plumbing::InternedStorage<Self>;
type Group = InternerDatabase;
type GroupStorage = StringInternerGroupStorage__;
type DynDb = dyn StringInterner;
const QUERY_INDEX: u16 = 0u16;
const QUERY_NAME: &'static str = "intern_string";
fn query_storage(group_storage: &Self::GroupStorage) -> &std::sync::Arc<Self::Storage> {
&group_storage.intern_string
}
}
pub struct InternStringLookupQuery;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::default::Default for InternStringLookupQuery {
#[inline]
fn default() -> InternStringLookupQuery {
InternStringLookupQuery {}
}
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for InternStringLookupQuery {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
InternStringLookupQuery => {
let mut debug_trait_builder = f.debug_tuple("InternStringLookupQuery");
debug_trait_builder.finish()
}
}
}
}
impl InternStringLookupQuery {
/// Get access to extra methods pertaining to this query. For
/// example, you can use this to run the GC (`sweep`) across a
/// single input. You can also use it to invoke this query, though
/// it's more common to use the trait method on the database
/// itself.
pub fn in_db(self, db: &dyn StringInterner) -> salsa::QueryTable<'_, Self> {
salsa::plumbing::get_query_table::<InternStringLookupQuery>(db)
}
}
impl InternStringLookupQuery {
/// Like `in_db`, but gives access to methods for setting the
/// value of an input. Not applicable to derived queries.
///
/// # Threads, cancellation, and blocking
///
/// Mutating the value of a query cannot be done while there are
/// still other queries executing. If you are using your database
/// within a single thread, this is not a problem: you only have
/// `&self` access to the database, but this method requires `&mut
/// self`.
///
/// However, if you have used `snapshot` to create other threads,
/// then attempts to `set` will **block the current thread** until
/// those snapshots are dropped (usually when those threads
/// complete). This also implies that if you create a snapshot but
/// do not send it to another thread, then invoking `set` will
/// deadlock.
///
/// Before blocking, the thread that is attempting to `set` will
/// also set a cancellation flag. In the threads operating on
/// snapshots, you can use the [`is_current_revision_canceled`]
/// method to check for this flag and bring those operations to a
/// close, thus allowing the `set` to succeed. Ignoring this flag
/// may lead to "starvation", meaning that the thread attempting
/// to `set` has to wait a long, long time. =)
///
/// [`is_current_revision_canceled`]: struct.Runtime.html#method.is_current_revision_canceled
pub fn in_db_mut(self, db: &mut dyn StringInterner) -> salsa::QueryTableMut<'_, Self> {
salsa::plumbing::get_query_table_mut::<InternStringLookupQuery>(db)
}
}
impl salsa::Query for InternStringLookupQuery {
type Key = (IStr);
type Value = (S);
type Storage = salsa::plumbing::LookupInternedStorage<Self, InternStringQuery>;
type Group = InternerDatabase;
type GroupStorage = StringInternerGroupStorage__;
type DynDb = dyn StringInterner;
const QUERY_INDEX: u16 = 1u16;
const QUERY_NAME: &'static str = "lookup_intern_string";
fn query_storage(group_storage: &Self::GroupStorage) -> &std::sync::Arc<Self::Storage> {
&group_storage.lookup_intern_string
}
}
pub struct StringInternerGroupStorage__ {
pub intern_string: std::sync::Arc<<InternStringQuery as salsa::Query>::Storage>,
pub lookup_intern_string:
std::sync::Arc<<InternStringLookupQuery as salsa::Query>::Storage>,
}
impl StringInternerGroupStorage__ {
pub fn new(group_index: u16) -> Self {
StringInternerGroupStorage__ {
intern_string: std::sync::Arc::new(salsa::plumbing::QueryStorageOps::new(
group_index,
)),
lookup_intern_string: std::sync::Arc::new(salsa::plumbing::QueryStorageOps::new(
group_index,
)),
}
}
}
impl StringInternerGroupStorage__ {
pub fn fmt_index(
&self,
db: &dyn StringInterner,
input: salsa::DatabaseKeyIndex,
fmt: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
match input.query_index() {
0u16 => salsa::plumbing::QueryStorageOps::fmt_index(
&*self.intern_string,
db,
input,
fmt,
),
1u16 => salsa::plumbing::QueryStorageOps::fmt_index(
&*self.lookup_intern_string,
db,
input,
fmt,
),
i => ::std::rt::begin_panic_fmt(&::core::fmt::Arguments::new_v1(
&["salsa: impossible query index "],
&match (&i,) {
(arg0,) => [::core::fmt::ArgumentV1::new(
arg0,
::core::fmt::Display::fmt,
)],
},
)),
}
}
pub fn maybe_changed_since(
&self,
db: &dyn StringInterner,
input: salsa::DatabaseKeyIndex,
revision: salsa::Revision,
) -> bool {
match input.query_index() {
0u16 => salsa::plumbing::QueryStorageOps::maybe_changed_since(
&*self.intern_string,
db,
input,
revision,
),
1u16 => salsa::plumbing::QueryStorageOps::maybe_changed_since(
&*self.lookup_intern_string,
db,
input,
revision,
),
i => ::std::rt::begin_panic_fmt(&::core::fmt::Arguments::new_v1(
&["salsa: impossible query index "],
&match (&i,) {
(arg0,) => [::core::fmt::ArgumentV1::new(
arg0,
::core::fmt::Display::fmt,
)],
},
)),
}
}
pub fn for_each_query(
&self,
_runtime: &salsa::Runtime,
mut op: &mut dyn FnMut(&dyn salsa::plumbing::QueryStorageMassOps),
) {
op(&*self.intern_string);
op(&*self.lookup_intern_string);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment