aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020/persistent_list.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2019-07-23 15:44:56 +0200
committerAnthony Ramine <n.oxyde@gmail.com>2019-07-31 17:09:16 +0200
commit4846d76e82e2d60875472fb8ea375e22d40a0800 (patch)
tree073ff8aa7ec1c65ad51c2b08bfe55007c6f442e7 /components/layout_2020/persistent_list.rs
parent87e7e3d429f2122ffa9ef016ba5659a3b21be91b (diff)
downloadservo-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.rs101
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)
+ }
+}