diff --git a/components/style/scoped_tls.rs b/components/style/scoped_tls.rs index 1f695aaa4c9..92cfd2a4659 100644 --- a/components/style/scoped_tls.rs +++ b/components/style/scoped_tls.rs @@ -2,22 +2,31 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +//! Stack-scoped thread-local storage for rayon thread pools. + #![allow(unsafe_code)] +#![deny(missing_docs)] use rayon; use std::cell::{Ref, RefCell, RefMut}; -/// Stack-scoped thread-local storage for rayon thread pools. - -pub struct ScopedTLS<'a, T: Send> { - pool: &'a rayon::ThreadPool, +/// A scoped TLS set, that is alive during the `'scope` lifetime. +/// +/// We use this on Servo to construct thread-local contexts, but clear them once +/// we're done with restyling. +pub struct ScopedTLS<'scope, T: Send> { + pool: &'scope rayon::ThreadPool, slots: Box<[RefCell>]>, } -unsafe impl<'a, T: Send> Sync for ScopedTLS<'a, T> {} +/// The scoped TLS is `Sync` because no more than one worker thread can access a +/// given slot. +unsafe impl<'scope, T: Send> Sync for ScopedTLS<'scope, T> {} -impl<'a, T: Send> ScopedTLS<'a, T> { - pub fn new(p: &'a rayon::ThreadPool) -> Self { +impl<'scope, T: Send> ScopedTLS<'scope, T> { + /// Create a new scoped TLS that will last as long as this rayon threadpool + /// reference. + pub fn new(p: &'scope rayon::ThreadPool) -> Self { let count = p.num_threads(); let mut v = Vec::with_capacity(count); for _ in 0..count { @@ -30,16 +39,20 @@ impl<'a, T: Send> ScopedTLS<'a, T> { } } + /// Return an immutable reference to the `Option` that this thread owns. pub fn borrow(&self) -> Ref> { let idx = self.pool.current_thread_index().unwrap(); self.slots[idx].borrow() } + /// Return a mutable reference to the `Option` that this thread owns. pub fn borrow_mut(&self) -> RefMut> { let idx = self.pool.current_thread_index().unwrap(); self.slots[idx].borrow_mut() } + /// Ensure that the current data this thread owns is initialized, or + /// initialize it using `f`. pub fn ensure T>(&self, f: F) -> RefMut { let mut opt = self.borrow_mut(); if opt.is_none() {