mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Introduce a RwData struct.
This commit is contained in:
parent
b8d8505463
commit
3f4c734cf4
1 changed files with 78 additions and 82 deletions
|
@ -311,6 +311,36 @@ impl<'a> DerefMut for RWGuard<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
struct RwData<'a, 'b: 'a> {
|
||||
rw_data: &'b Arc<Mutex<LayoutTaskData>>,
|
||||
possibly_locked_rw_data: &'a mut Option<MutexGuard<'b, LayoutTaskData>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> RwData<'a, 'b> {
|
||||
/// If no reflow has happened yet, this will just return the lock in
|
||||
/// `possibly_locked_rw_data`. Otherwise, it will acquire the `rw_data` lock.
|
||||
///
|
||||
/// If you do not wish RPCs to remain blocked, just drop the `RWGuard`
|
||||
/// returned from this function. If you _do_ wish for them to remain blocked,
|
||||
/// use `block`.
|
||||
fn lock(&mut self) -> RWGuard<'b> {
|
||||
match self.possibly_locked_rw_data.take() {
|
||||
None => RWGuard::Used(self.rw_data.lock().unwrap()),
|
||||
Some(x) => RWGuard::Held(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// If no reflow has ever been triggered, this will keep the lock, locked
|
||||
/// (and saved in `possibly_locked_rw_data`). If it has been, the lock will
|
||||
/// be unlocked.
|
||||
fn block(&mut self, rw_data: RWGuard<'b>) {
|
||||
match rw_data {
|
||||
RWGuard::Used(x) => drop(x),
|
||||
RWGuard::Held(x) => *self.possibly_locked_rw_data = Some(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_font_face_rules(stylesheet: &Stylesheet,
|
||||
device: &Device,
|
||||
font_cache_task: &FontCacheTask,
|
||||
|
@ -432,8 +462,13 @@ impl LayoutTask {
|
|||
|
||||
/// Starts listening on the port.
|
||||
fn start(self) {
|
||||
let mut possibly_locked_rw_data = Some((*self.rw_data).lock().unwrap());
|
||||
while self.handle_request(&mut possibly_locked_rw_data) {
|
||||
let rw_data = self.rw_data.clone();
|
||||
let mut possibly_locked_rw_data = Some(rw_data.lock().unwrap());
|
||||
let mut rw_data = RwData {
|
||||
rw_data: &rw_data,
|
||||
possibly_locked_rw_data: &mut possibly_locked_rw_data,
|
||||
};
|
||||
while self.handle_request(&mut rw_data) {
|
||||
// Loop indefinitely.
|
||||
}
|
||||
}
|
||||
|
@ -463,9 +498,7 @@ impl LayoutTask {
|
|||
}
|
||||
|
||||
/// Receives and dispatches messages from the script and constellation tasks
|
||||
fn handle_request<'a>(&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>)
|
||||
-> bool {
|
||||
fn handle_request<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) -> bool {
|
||||
enum Request {
|
||||
FromPipeline(LayoutControlMsg),
|
||||
FromScript(Msg),
|
||||
|
@ -521,7 +554,7 @@ impl LayoutTask {
|
|||
self.repaint(possibly_locked_rw_data)
|
||||
},
|
||||
Request::FromFontCache => {
|
||||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let rw_data = possibly_locked_rw_data.lock();
|
||||
rw_data.outstanding_web_fonts.fetch_sub(1, Ordering::SeqCst);
|
||||
font_context::invalidate_font_caches();
|
||||
self.script_chan.send(ConstellationControlMsg::WebFontLoaded(self.id)).unwrap();
|
||||
|
@ -530,40 +563,13 @@ impl LayoutTask {
|
|||
}
|
||||
}
|
||||
|
||||
/// If no reflow has happened yet, this will just return the lock in
|
||||
/// `possibly_locked_rw_data`. Otherwise, it will acquire the `rw_data` lock.
|
||||
///
|
||||
/// If you do not wish RPCs to remain blocked, just drop the `RWGuard`
|
||||
/// returned from this function. If you _do_ wish for them to remain blocked,
|
||||
/// use `return_rw_data`.
|
||||
fn lock_rw_data<'a>(&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>)
|
||||
-> RWGuard<'a> {
|
||||
match possibly_locked_rw_data.take() {
|
||||
None => RWGuard::Used((*self.rw_data).lock().unwrap()),
|
||||
Some(x) => RWGuard::Held(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// If no reflow has ever been triggered, this will keep the lock, locked
|
||||
/// (and saved in `possibly_locked_rw_data`). If it has been, the lock will
|
||||
/// be unlocked.
|
||||
fn return_rw_data<'a>(possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>,
|
||||
rw_data: RWGuard<'a>) {
|
||||
match rw_data {
|
||||
RWGuard::Used(x) => drop(x),
|
||||
RWGuard::Held(x) => *possibly_locked_rw_data = Some(x),
|
||||
}
|
||||
}
|
||||
|
||||
/// Repaint the scene, without performing style matching. This is typically
|
||||
/// used when an image arrives asynchronously and triggers a relayout and
|
||||
/// repaint.
|
||||
/// TODO: In the future we could detect if the image size hasn't changed
|
||||
/// since last time and avoid performing a complete layout pass.
|
||||
fn repaint<'a>(&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) -> bool {
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
fn repaint<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) -> bool {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
|
||||
let reflow_info = Reflow {
|
||||
goal: ReflowGoal::ForDisplay,
|
||||
|
@ -584,11 +590,10 @@ impl LayoutTask {
|
|||
}
|
||||
|
||||
/// Receives and dispatches messages from other tasks.
|
||||
fn handle_request_helper<'a>(&'a self,
|
||||
request: Msg,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a,
|
||||
LayoutTaskData>>)
|
||||
-> bool {
|
||||
fn handle_request_helper<'a, 'b>(&self,
|
||||
request: Msg,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>)
|
||||
-> bool {
|
||||
match request {
|
||||
Msg::AddStylesheet(style_info) => {
|
||||
self.handle_add_stylesheet(style_info, possibly_locked_rw_data)
|
||||
|
@ -620,11 +625,11 @@ impl LayoutTask {
|
|||
self.collect_reports(reports_chan, possibly_locked_rw_data);
|
||||
},
|
||||
Msg::GetCurrentEpoch(sender) => {
|
||||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let rw_data = possibly_locked_rw_data.lock();
|
||||
sender.send(rw_data.epoch).unwrap();
|
||||
},
|
||||
Msg::GetWebFontLoadState(sender) => {
|
||||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let rw_data = possibly_locked_rw_data.lock();
|
||||
let outstanding_web_fonts = rw_data.outstanding_web_fonts.load(Ordering::SeqCst);
|
||||
sender.send(outstanding_web_fonts != 0).unwrap();
|
||||
},
|
||||
|
@ -645,13 +650,13 @@ impl LayoutTask {
|
|||
true
|
||||
}
|
||||
|
||||
fn collect_reports<'a>(&'a self,
|
||||
reports_chan: ReportsChan,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
fn collect_reports<'a, 'b>(&self,
|
||||
reports_chan: ReportsChan,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
let mut reports = vec![];
|
||||
|
||||
// FIXME(njn): Just measuring the display tree for now.
|
||||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let rw_data = possibly_locked_rw_data.lock();
|
||||
let stacking_context = rw_data.stacking_context.as_ref();
|
||||
reports.push(Report {
|
||||
path: path![format!("url({})", self.url), "layout-task", "display-list"],
|
||||
|
@ -704,9 +709,9 @@ impl LayoutTask {
|
|||
|
||||
/// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is
|
||||
/// received. A pong is immediately sent on the given response channel.
|
||||
fn prepare_to_exit<'a>(&'a self,
|
||||
response_chan: Sender<()>,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
fn prepare_to_exit<'a, 'b>(&self,
|
||||
response_chan: Sender<()>,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
response_chan.send(()).unwrap();
|
||||
loop {
|
||||
match self.port.recv().unwrap() {
|
||||
|
@ -732,14 +737,13 @@ impl LayoutTask {
|
|||
|
||||
/// Shuts down the layout task now. If there are any DOM nodes left, layout will now (safely)
|
||||
/// crash.
|
||||
fn exit_now<'a>(&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
fn exit_now<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
{
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
if let Some(ref mut traversal) = (&mut *rw_data).parallel_traversal {
|
||||
traversal.shutdown()
|
||||
}
|
||||
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
|
||||
possibly_locked_rw_data.block(rw_data);
|
||||
}
|
||||
|
||||
let (response_chan, response_port) = ipc::channel().unwrap();
|
||||
|
@ -747,14 +751,13 @@ impl LayoutTask {
|
|||
response_port.recv().unwrap()
|
||||
}
|
||||
|
||||
fn handle_add_stylesheet<'a>(&'a self,
|
||||
stylesheet: Arc<Stylesheet>,
|
||||
possibly_locked_rw_data:
|
||||
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
fn handle_add_stylesheet<'a, 'b>(&self,
|
||||
stylesheet: Arc<Stylesheet>,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
// Find all font-face rules and notify the font cache of them.
|
||||
// GWTODO: Need to handle unloading web fonts.
|
||||
|
||||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let rw_data = possibly_locked_rw_data.lock();
|
||||
if stylesheet.is_effective_for_device(&rw_data.stylist.device) {
|
||||
add_font_face_rules(&*stylesheet,
|
||||
&rw_data.stylist.device,
|
||||
|
@ -763,16 +766,14 @@ impl LayoutTask {
|
|||
&rw_data.outstanding_web_fonts);
|
||||
}
|
||||
|
||||
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
|
||||
possibly_locked_rw_data.block(rw_data);
|
||||
}
|
||||
|
||||
/// Sets quirks mode for the document, causing the quirks mode stylesheet to be used.
|
||||
fn handle_set_quirks_mode<'a>(&'a self,
|
||||
possibly_locked_rw_data:
|
||||
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
fn handle_set_quirks_mode<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
rw_data.stylist.set_quirks_mode(true);
|
||||
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
|
||||
possibly_locked_rw_data.block(rw_data);
|
||||
}
|
||||
|
||||
fn try_get_layout_root(&self, node: LayoutNode) -> Option<FlowRef> {
|
||||
|
@ -1084,10 +1085,9 @@ impl LayoutTask {
|
|||
}
|
||||
|
||||
/// The high-level routine that performs layout tasks.
|
||||
fn handle_reflow<'a>(&'a self,
|
||||
data: &ScriptReflow,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
|
||||
fn handle_reflow<'a, 'b>(&self,
|
||||
data: &ScriptReflow,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
// Make sure that every return path from this method joins the script task,
|
||||
// otherwise the script task will panic.
|
||||
struct AutoJoinScriptTask<'a> { data: &'a ScriptReflow };
|
||||
|
@ -1110,7 +1110,7 @@ impl LayoutTask {
|
|||
node.dump();
|
||||
}
|
||||
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
let stylesheets: Vec<&Stylesheet> = data.document_stylesheets.iter().map(|entry| &**entry)
|
||||
.collect();
|
||||
let stylesheets_changed = data.stylesheets_changed;
|
||||
|
@ -1232,11 +1232,11 @@ impl LayoutTask {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_visible_rects<'a>(&'a self,
|
||||
new_visible_rects: Vec<(LayerId, Rect<Au>)>,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>)
|
||||
-> bool {
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
fn set_visible_rects<'a, 'b>(&self,
|
||||
new_visible_rects: Vec<(LayerId, Rect<Au>)>,
|
||||
possibly_locked_rw_data: &mut RwData<'a, 'b>)
|
||||
-> bool {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
|
||||
// First, determine if we need to regenerate the display lists. This will happen if the
|
||||
// layers have moved more than `DISPLAY_PORT_THRESHOLD_SIZE_FACTOR` away from their last
|
||||
|
@ -1289,10 +1289,8 @@ impl LayoutTask {
|
|||
true
|
||||
}
|
||||
|
||||
fn tick_all_animations<'a>(&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a,
|
||||
LayoutTaskData>>) {
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
fn tick_all_animations<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
animation::tick_all_animations(self, &mut rw_data)
|
||||
}
|
||||
|
||||
|
@ -1324,10 +1322,8 @@ impl LayoutTask {
|
|||
&mut layout_context);
|
||||
}
|
||||
|
||||
pub fn reflow_with_newly_loaded_web_font<'a>(
|
||||
&'a self,
|
||||
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
|
||||
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
fn reflow_with_newly_loaded_web_font<'a, 'b>(&self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
font_context::invalidate_font_caches();
|
||||
|
||||
let reflow_info = Reflow {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue