diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-06-29 06:38:48 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-07-01 05:22:50 -0400 |
| commit | 388ff03248f15b6266f8614e1a3f10e28fcbb1e3 (patch) | |
| tree | d62788e232cb2e957f83d4f0f2ca42bbcdbaf28d /src/librustc_data_structures | |
| parent | a1703baf520b8c14f50719c9ffa8036f3b782134 (diff) | |
create a new `WorkQueue` data structure
Diffstat (limited to 'src/librustc_data_structures')
| -rw-r--r-- | src/librustc_data_structures/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_data_structures/work_queue.rs | 72 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 5844edf000a..e4d0bc596cb 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -77,6 +77,7 @@ pub mod sync; pub mod owning_ref; pub mod tiny_list; pub mod sorted_map; +pub mod work_queue; pub struct OnDrop<F: Fn()>(pub F); diff --git a/src/librustc_data_structures/work_queue.rs b/src/librustc_data_structures/work_queue.rs new file mode 100644 index 00000000000..b8e8b249bb5 --- /dev/null +++ b/src/librustc_data_structures/work_queue.rs @@ -0,0 +1,72 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use indexed_set::IdxSetBuf; +use indexed_vec::Idx; +use std::collections::VecDeque; + +/// A work queue is a handy data structure for tracking work left to +/// do. (For example, basic blocks left to process.) It is basically a +/// de-duplicating queue; so attempting to insert X if X is already +/// enqueued has no effect. This implementation assumes that the +/// elements are dense indices, so it can allocate the queue to size +/// and also use a bit set to track occupancy. +pub struct WorkQueue<T: Idx> { + deque: VecDeque<T>, + set: IdxSetBuf<T>, +} + +impl<T: Idx> WorkQueue<T> { + /// Create a new work queue with all the elements from (0..len). + #[inline] + pub fn with_all(len: usize) -> Self { + WorkQueue { + deque: (0..len).map(T::new).collect(), + set: IdxSetBuf::new_filled(len), + } + } + + /// Create a new work queue that starts empty, where elements range from (0..len). + #[inline] + pub fn with_none(len: usize) -> Self { + WorkQueue { + deque: VecDeque::with_capacity(len), + set: IdxSetBuf::new_empty(len), + } + } + + /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. + #[inline] + pub fn insert(&mut self, element: T) -> bool { + if self.set.add(&element) { + self.deque.push_back(element); + true + } else { + false + } + } + + /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. + #[inline] + pub fn pop(&mut self) -> Option<T> { + if let Some(element) = self.deque.pop_front() { + self.set.remove(&element); + Some(element) + } else { + None + } + } + + /// True if nothing is enqueued. + #[inline] + pub fn is_empty(&self) -> bool { + self.deque.is_empty() + } +} |
