Struct Graph

Source
pub struct Graph<Q, R> { /* private fields */ }
Expand description

The Graph struct represents a concurrent query dependency graph. It provides the infrastructure for managing, resolving, and optimizing a wide range of queries across a variety of applications, including but not limited to concurrent incremental compilers.

§Overview

A Graph instance serves as the central data structure for tracking and managing dependencies between queries (Q) and their respective results (R). This data structure is completely agnostic to the specific use case, and its generic nature makes it adaptable to a multitude of scenarios beyond compiler optimization.

§Query Resolution

The Graph type allows for concurrent query resolution, where queries can be resolved in parallel, enhancing performance significantly. The increment method does not block and returns a new iteration of the graph immediately. In fact, the Graph.query method is designed to block as little as possible. In the general case it will block extremely infrequently. This means that queries will be able to continue chugging away as fast as possible with little to no interruptions.

§Structure

  • new: A QueryNodeMap representing the current state of queries for the current iteration. All new queries and their results are stored in this map. It begins each iteration as an empty map.

  • old: A QueryNodeMap serving as a reference to the map from the previous iteration. It is used for validating queries and their results from the current iteration. This reference mechanism provides an efficient way to track and compare query changes across iterations.

  • resolver: An associated type (ResolveQuery) used to resolve queries and obtain their results. This type may carry its own state as long as it implements the Sync and Send traits, enabling it to work seamlessly in a multithreaded environment.

§Incremental Compilation

In the context of a concurrent incremental compiler, only queries that are determined to be outdated are resolved again. This approach greatly reduces the time required to resolve queries, making the example compiler incremental. The semantic model is still built every time you mutate the compiler’s state, but most of the work is already done and can be reused, resulting in extremely fast model building.

§Usage

The Graph type can be employed in a wide range of applications, from compilers to data processing pipelines and more. Its flexibility allows developers to adapt it to their specific use cases.

§Considerations

  • The Graph is a versatile data structure that can be applied in various scenarios beyond compilers. Its flexibility allows developers to adapt it to their specific use cases.

  • The resolver associated with the Graph should be chosen based on the requirements of the application and its thread safety characteristics.

Implementations§

Source§

impl<Q: Clone + Eq + Hash + Send + Sync, R: Clone + Eq + Send + Sync> Graph<Q, R>

Source

pub fn new(resolver: impl ResolveQuery<Q, R> + 'static) -> Arc<Self>

Source

pub fn query(self: &Arc<Self>, q: Q) -> R

Source

pub fn increment( self: &Arc<Self>, resolver: impl ResolveQuery<Q, R> + 'static, ) -> Arc<Self>

Trait Implementations§

Source§

impl<Q: Debug + Clone + Eq + Hash, R: Debug + Clone> Debug for Graph<Q, R>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<Q, R> Freeze for Graph<Q, R>

§

impl<Q, R> !RefUnwindSafe for Graph<Q, R>

§

impl<Q, R> Send for Graph<Q, R>
where Q: Send + Sync, R: Sync + Send,

§

impl<Q, R> Sync for Graph<Q, R>
where Q: Send + Sync, R: Sync + Send,

§

impl<Q, R> Unpin for Graph<Q, R>

§

impl<Q, R> !UnwindSafe for Graph<Q, R>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.