diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2019-07-23 15:44:56 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2019-07-31 17:09:16 +0200 |
commit | 4846d76e82e2d60875472fb8ea375e22d40a0800 (patch) | |
tree | 073ff8aa7ec1c65ad51c2b08bfe55007c6f442e7 /components/layout_2020/persistent_list.rs | |
parent | 87e7e3d429f2122ffa9ef016ba5659a3b21be91b (diff) | |
download | servo-4846d76e82e2d60875472fb8ea375e22d40a0800.tar.gz servo-4846d76e82e2d60875472fb8ea375e22d40a0800.zip |
Make layout_2020 be layout_2013
Diffstat (limited to 'components/layout_2020/persistent_list.rs')
-rw-r--r-- | components/layout_2020/persistent_list.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/components/layout_2020/persistent_list.rs b/components/layout_2020/persistent_list.rs new file mode 100644 index 00000000000..16bbc319ea0 --- /dev/null +++ b/components/layout_2020/persistent_list.rs @@ -0,0 +1,101 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! A persistent, thread-safe singly-linked list. + +use std::sync::Arc; + +pub struct PersistentList<T> { + head: PersistentListLink<T>, + length: usize, +} + +struct PersistentListEntry<T> { + value: T, + next: PersistentListLink<T>, +} + +type PersistentListLink<T> = Option<Arc<PersistentListEntry<T>>>; + +impl<T> PersistentList<T> +where + T: Send + Sync, +{ + #[inline] + pub fn new() -> PersistentList<T> { + PersistentList { + head: None, + length: 0, + } + } + + #[inline] + pub fn len(&self) -> usize { + self.length + } + + #[inline] + pub fn front(&self) -> Option<&T> { + self.head.as_ref().map(|head| &head.value) + } + + #[inline] + pub fn prepend_elem(&self, value: T) -> PersistentList<T> { + PersistentList { + head: Some(Arc::new(PersistentListEntry { + value: value, + next: self.head.clone(), + })), + length: self.length + 1, + } + } + + #[inline] + pub fn iter(&self) -> PersistentListIterator<T> { + // This could clone (and would not need the lifetime if it did), but then it would incur + // atomic operations on every call to `.next()`. Bad. + PersistentListIterator { + entry: self.head.as_ref().map(|head| &**head), + } + } +} + +impl<T> Clone for PersistentList<T> +where + T: Send + Sync, +{ + fn clone(&self) -> PersistentList<T> { + // This establishes the persistent nature of this list: we can clone a list by just cloning + // its head. + PersistentList { + head: self.head.clone(), + length: self.length, + } + } +} + +pub struct PersistentListIterator<'a, T> +where + T: Send + Sync, +{ + entry: Option<&'a PersistentListEntry<T>>, +} + +impl<'a, T> Iterator for PersistentListIterator<'a, T> +where + T: Send + Sync + 'static, +{ + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + let entry = self.entry?; + let value = &entry.value; + self.entry = match entry.next { + None => None, + Some(ref entry) => Some(&**entry), + }; + Some(value) + } +} |