Skip to content

Commit

Permalink
Use a unique queue for pending analyses (#253)
Browse files Browse the repository at this point in the history
* Use a unique queue for pending analyses

* implement (De)Serialize for UniqueQueue

* fix serialize nit test

* cargo fmt

---------

Co-authored-by: thomas <Thomas Koehler>
  • Loading branch information
Bastacyclop authored May 2, 2023
1 parent 164d2b3 commit 2f106a4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/egraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub struct EGraph<L: Language, N: Analysis<L>> {
/// Nodes which need to be processed for rebuilding. The `Id` is the `Id` of the enode,
/// not the canonical id of the eclass.
pending: Vec<(L, Id)>,
analysis_pending: IndexSet<(L, Id)>,
analysis_pending: UniqueQueue<(L, Id)>,
#[cfg_attr(
feature = "serde-1",
serde(bound(
Expand Down
61 changes: 61 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use symbolic_expressions::Sexp;

use fmt::{Debug, Display, Formatter};

#[cfg(feature = "serde-1")]
use ::serde::{Deserialize, Serialize};

#[allow(unused_imports)]
use crate::*;

Expand Down Expand Up @@ -111,3 +114,61 @@ impl<T: Display> Debug for DisplayAsDebug<T> {
Display::fmt(&self.0, f)
}
}

/** A data structure to maintain a queue of unique elements.
Notably, insert/pop operations have O(1) expected amortized runtime complexity.
*/
#[derive(Clone)]
#[cfg_attr(feature = "serde-1", derive(Serialize, Deserialize))]
pub(crate) struct UniqueQueue<T>
where
T: Eq + std::hash::Hash + Clone,
{
set: hashbrown::HashSet<T>,
queue: std::collections::VecDeque<T>,
}

impl<T> Default for UniqueQueue<T>
where
T: Eq + std::hash::Hash + Clone,
{
fn default() -> Self {
UniqueQueue {
set: hashbrown::HashSet::default(),
queue: std::collections::VecDeque::new(),
}
}
}

impl<T> UniqueQueue<T>
where
T: Eq + std::hash::Hash + Clone,
{
pub fn insert(&mut self, t: T) {
if self.set.insert(t.clone()) {
self.queue.push_back(t);
}
}

pub fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
for t in iter.into_iter() {
self.insert(t);
}
}

pub fn pop(&mut self) -> Option<T> {
let res = self.queue.pop_front();
res.as_ref().map(|t| self.set.remove(t));
res
}

pub fn is_empty(&self) -> bool {
let r = self.queue.is_empty();
debug_assert_eq!(r, self.set.is_empty());
r
}
}

0 comments on commit 2f106a4

Please sign in to comment.