mirror of
https://github.com/servo/servo.git
synced 2025-08-08 23:15:33 +01:00
Replace RwLock<MediaList> with shared_lock::Locked<MediaList>
This commit is contained in:
parent
8feb9e8047
commit
c5a7294e05
18 changed files with 117 additions and 42 deletions
|
@ -12,6 +12,7 @@ use media_queries::MediaList;
|
|||
use parser::ParserContextExtraData;
|
||||
use self::encoding::{EncodingRef, DecoderTrap};
|
||||
use servo_url::ServoUrl;
|
||||
use shared_lock::SharedRwLock;
|
||||
use std::str;
|
||||
use stylesheets::{Stylesheet, StylesheetLoader, Origin};
|
||||
|
||||
|
@ -54,6 +55,7 @@ impl Stylesheet {
|
|||
environment_encoding: Option<EncodingRef>,
|
||||
origin: Origin,
|
||||
media: MediaList,
|
||||
shared_lock: SharedRwLock,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &ParseErrorReporter,
|
||||
extra_data: ParserContextExtraData)
|
||||
|
@ -64,6 +66,7 @@ impl Stylesheet {
|
|||
base_url,
|
||||
origin,
|
||||
media,
|
||||
shared_lock,
|
||||
stylesheet_loader,
|
||||
error_reporter,
|
||||
extra_data)
|
||||
|
|
|
@ -21,6 +21,7 @@ use selector_parser::{SelectorImpl, SelectorParser};
|
|||
use selectors::parser::SelectorList;
|
||||
use servo_config::prefs::PREFS;
|
||||
use servo_url::ServoUrl;
|
||||
use shared_lock::{SharedRwLock, Locked, SharedRwLockReadGuard};
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
@ -175,11 +176,13 @@ pub struct Stylesheet {
|
|||
/// cascading order)
|
||||
pub rules: Arc<RwLock<CssRules>>,
|
||||
/// List of media associated with the Stylesheet.
|
||||
pub media: Arc<RwLock<MediaList>>,
|
||||
pub media: Arc<Locked<MediaList>>,
|
||||
/// The origin of this stylesheet.
|
||||
pub origin: Origin,
|
||||
/// The base url this stylesheet should use.
|
||||
pub base_url: ServoUrl,
|
||||
/// The lock used for objects inside this stylesheet
|
||||
pub shared_lock: SharedRwLock,
|
||||
/// The namespaces that apply to this stylesheet.
|
||||
pub namespaces: RwLock<Namespaces>,
|
||||
/// Whether this stylesheet would be dirty when the viewport size changes.
|
||||
|
@ -191,6 +194,8 @@ pub struct Stylesheet {
|
|||
|
||||
/// This structure holds the user-agent and user stylesheets.
|
||||
pub struct UserAgentStylesheets {
|
||||
/// The lock used for user-agent stylesheets.
|
||||
pub shared_lock: SharedRwLock,
|
||||
/// The user or user agent stylesheets.
|
||||
pub user_or_user_agent_stylesheets: Vec<Stylesheet>,
|
||||
/// The quirks mode stylesheet.
|
||||
|
@ -291,12 +296,12 @@ impl CssRule {
|
|||
/// used for others.
|
||||
///
|
||||
/// This will not recurse down unsupported @supports rules
|
||||
pub fn with_nested_rules_and_mq<F, R>(&self, mut f: F) -> R
|
||||
pub fn with_nested_rules_and_mq<F, R>(&self, guard: &SharedRwLockReadGuard, mut f: F) -> R
|
||||
where F: FnMut(&[CssRule], Option<&MediaList>) -> R {
|
||||
match *self {
|
||||
CssRule::Import(ref lock) => {
|
||||
let rule = lock.read();
|
||||
let media = rule.stylesheet.media.read();
|
||||
let media = rule.stylesheet.media.read_with(guard);
|
||||
let rules = rule.stylesheet.rules.read();
|
||||
// FIXME(emilio): Include the nested rules if the stylesheet is
|
||||
// loaded.
|
||||
|
@ -349,6 +354,7 @@ impl CssRule {
|
|||
let mut rule_parser = TopLevelRuleParser {
|
||||
stylesheet_origin: parent_stylesheet.origin,
|
||||
context: context,
|
||||
shared_lock: &parent_stylesheet.shared_lock,
|
||||
loader: None,
|
||||
state: Cell::new(state),
|
||||
namespaces: &mut namespaces,
|
||||
|
@ -424,7 +430,8 @@ impl ToCss for ImportRule {
|
|||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
try!(dest.write_str("@import "));
|
||||
try!(self.url.to_css(dest));
|
||||
let media = self.stylesheet.media.read();
|
||||
let guard = self.stylesheet.shared_lock.read(); // FIXME: have the caller pass this?
|
||||
let media = self.stylesheet.media.read_with(&guard);
|
||||
if !media.is_empty() {
|
||||
try!(dest.write_str(" "));
|
||||
try!(media.to_css(dest));
|
||||
|
@ -554,6 +561,7 @@ impl Stylesheet {
|
|||
let rule_parser = TopLevelRuleParser {
|
||||
stylesheet_origin: existing.origin,
|
||||
namespaces: &mut namespaces,
|
||||
shared_lock: &existing.shared_lock,
|
||||
loader: stylesheet_loader,
|
||||
context: ParserContext::new_with_extra_data(existing.origin,
|
||||
&existing.base_url,
|
||||
|
@ -591,6 +599,7 @@ impl Stylesheet {
|
|||
base_url: ServoUrl,
|
||||
origin: Origin,
|
||||
media: MediaList,
|
||||
shared_lock: SharedRwLock,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &ParseErrorReporter,
|
||||
extra_data: ParserContextExtraData) -> Stylesheet {
|
||||
|
@ -599,7 +608,8 @@ impl Stylesheet {
|
|||
base_url: base_url,
|
||||
namespaces: RwLock::new(Namespaces::default()),
|
||||
rules: CssRules::new(vec![]),
|
||||
media: Arc::new(RwLock::new(media)),
|
||||
media: Arc::new(shared_lock.wrap(media)),
|
||||
shared_lock: shared_lock.clone(),
|
||||
dirty_on_viewport_size_change: AtomicBool::new(false),
|
||||
disabled: AtomicBool::new(false),
|
||||
};
|
||||
|
@ -638,7 +648,8 @@ impl Stylesheet {
|
|||
///
|
||||
/// Always true if no associated MediaList exists.
|
||||
pub fn is_effective_for_device(&self, device: &Device) -> bool {
|
||||
self.media.read().evaluate(device)
|
||||
let guard = self.shared_lock.read(); // FIXME: have the caller pass this?
|
||||
self.media.read_with(&guard).evaluate(device)
|
||||
}
|
||||
|
||||
/// Return an iterator over the effective rules within the style-sheet, as
|
||||
|
@ -649,7 +660,8 @@ impl Stylesheet {
|
|||
/// examined.
|
||||
#[inline]
|
||||
pub fn effective_rules<F>(&self, device: &Device, mut f: F) where F: FnMut(&CssRule) {
|
||||
effective_rules(&self.rules.read().0, device, &mut f);
|
||||
let guard = self.shared_lock.read(); // FIXME: have the caller pass this?
|
||||
effective_rules(&self.rules.read().0, device, &guard, &mut f);
|
||||
}
|
||||
|
||||
/// Returns whether the stylesheet has been explicitly disabled through the
|
||||
|
@ -670,16 +682,17 @@ impl Stylesheet {
|
|||
}
|
||||
}
|
||||
|
||||
fn effective_rules<F>(rules: &[CssRule], device: &Device, f: &mut F) where F: FnMut(&CssRule) {
|
||||
fn effective_rules<F>(rules: &[CssRule], device: &Device, guard: &SharedRwLockReadGuard, f: &mut F)
|
||||
where F: FnMut(&CssRule) {
|
||||
for rule in rules {
|
||||
f(rule);
|
||||
rule.with_nested_rules_and_mq(|rules, mq| {
|
||||
rule.with_nested_rules_and_mq(guard, |rules, mq| {
|
||||
if let Some(media_queries) = mq {
|
||||
if !media_queries.evaluate(device) {
|
||||
return
|
||||
}
|
||||
}
|
||||
effective_rules(rules, device, f)
|
||||
effective_rules(rules, device, guard, f)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -724,6 +737,7 @@ pub trait StylesheetLoader {
|
|||
struct TopLevelRuleParser<'a> {
|
||||
stylesheet_origin: Origin,
|
||||
namespaces: &'a mut Namespaces,
|
||||
shared_lock: &'a SharedRwLock,
|
||||
loader: Option<&'a StylesheetLoader>,
|
||||
context: ParserContext<'a>,
|
||||
state: Cell<State>,
|
||||
|
@ -780,7 +794,7 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
&self.context));
|
||||
|
||||
let media =
|
||||
Arc::new(RwLock::new(parse_media_query_list(input)));
|
||||
Arc::new(self.shared_lock.wrap(parse_media_query_list(input)));
|
||||
|
||||
let is_valid_url = url.url().is_some();
|
||||
|
||||
|
@ -790,6 +804,7 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
stylesheet: Arc::new(Stylesheet {
|
||||
rules: Arc::new(RwLock::new(CssRules(vec![]))),
|
||||
media: media,
|
||||
shared_lock: self.shared_lock.clone(),
|
||||
origin: self.context.stylesheet_origin,
|
||||
base_url: self.context.base_url.clone(),
|
||||
namespaces: RwLock::new(Namespaces::default()),
|
||||
|
|
|
@ -28,6 +28,7 @@ use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONA
|
|||
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_complex_selector};
|
||||
use selectors::parser::{Selector, SimpleSelector, LocalName as LocalNameSelector, ComplexSelector};
|
||||
use selectors::parser::SelectorMethods;
|
||||
#[cfg(feature = "servo")] use shared_lock::SharedRwLockReadGuard;
|
||||
use sink::Push;
|
||||
use smallvec::VecLike;
|
||||
use std::borrow::Borrow;
|
||||
|
@ -461,7 +462,8 @@ impl Stylist {
|
|||
/// FIXME(emilio): The semantics of the device for Servo and Gecko are
|
||||
/// different enough we may want to unify them.
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
|
||||
pub fn set_device(&mut self, mut device: Device, guard: &SharedRwLockReadGuard,
|
||||
stylesheets: &[Arc<Stylesheet>]) {
|
||||
let cascaded_rule = ViewportRule {
|
||||
declarations: viewport::Cascade::from_stylesheets(stylesheets, &device).finish(),
|
||||
};
|
||||
|
@ -473,15 +475,16 @@ impl Stylist {
|
|||
device.account_for_viewport_rule(constraints);
|
||||
}
|
||||
|
||||
fn mq_eval_changed(rules: &[CssRule], before: &Device, after: &Device) -> bool {
|
||||
fn mq_eval_changed(guard: &SharedRwLockReadGuard, rules: &[CssRule],
|
||||
before: &Device, after: &Device) -> bool {
|
||||
for rule in rules {
|
||||
let changed = rule.with_nested_rules_and_mq(|rules, mq| {
|
||||
let changed = rule.with_nested_rules_and_mq(guard, |rules, mq| {
|
||||
if let Some(mq) = mq {
|
||||
if mq.evaluate(before) != mq.evaluate(after) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
mq_eval_changed(rules, before, after)
|
||||
mq_eval_changed(guard, rules, before, after)
|
||||
});
|
||||
if changed {
|
||||
return true
|
||||
|
@ -490,12 +493,12 @@ impl Stylist {
|
|||
false
|
||||
}
|
||||
self.is_device_dirty |= stylesheets.iter().any(|stylesheet| {
|
||||
let mq = stylesheet.media.read();
|
||||
let mq = stylesheet.media.read_with(guard);
|
||||
if mq.evaluate(&self.device) != mq.evaluate(&device) {
|
||||
return true
|
||||
}
|
||||
|
||||
mq_eval_changed(&stylesheet.rules.read().0, &self.device, &device)
|
||||
mq_eval_changed(guard, &stylesheet.rules.read().0, &self.device, &device)
|
||||
});
|
||||
|
||||
self.device = Arc::new(device);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue