From 7eb4097dc917888268fa003f97ed652c5742174b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 26 Nov 2013 11:53:54 -0800 Subject: [PATCH 1/2] layout: Make the `LocalImageCache` `on_image_available` callback not use `@`. This is one small step toward parallel layout. --- src/components/main/layout/layout_task.rs | 6 +++--- src/components/net/local_image_cache.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 18b5d398990..46e9ca16457 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -675,15 +675,15 @@ impl LayoutTask { // to the script task, and ultimately cause the image to be // re-requested. We probably don't need to go all the way back to // the script task for this. - fn make_on_image_available_cb(&self) -> @ImageResponder { + fn make_on_image_available_cb(&self) -> ~ImageResponder:Send { // This has a crazy signature because the image cache needs to // make multiple copies of the callback, and the dom event // channel is not a copyable type, so this is actually a // little factory to produce callbacks - @LayoutImageResponder { + ~LayoutImageResponder { id: self.id.clone(), script_chan: self.script_chan.clone(), - } as @ImageResponder + } as ~ImageResponder:Send } /// Handles a message to destroy layout data. Layout data must be destroyed on *this* task diff --git a/src/components/net/local_image_cache.rs b/src/components/net/local_image_cache.rs index 2970c16bb5f..12521263a30 100644 --- a/src/components/net/local_image_cache.rs +++ b/src/components/net/local_image_cache.rs @@ -33,7 +33,7 @@ pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache { pub struct LocalImageCache { priv image_cache_task: ImageCacheTask, priv round_number: uint, - priv on_image_available: Option<@ImageResponder>, + priv on_image_available: Option<~ImageResponder:Send>, priv state_map: UrlMap<@mut ImageState> } @@ -47,7 +47,7 @@ struct ImageState { impl LocalImageCache { /// The local cache will only do a single remote request for a given /// URL in each 'round'. Layout should call this each time it begins - pub fn next_round(&mut self, on_image_available: @ImageResponder) { + pub fn next_round(&mut self, on_image_available: ~ImageResponder:Send) { self.round_number += 1; self.on_image_available = Some(on_image_available); } @@ -113,7 +113,7 @@ impl LocalImageCache { // on the image to load and triggering layout let image_cache_task = self.image_cache_task.clone(); assert!(self.on_image_available.is_some()); - let on_image_available = self.on_image_available.unwrap().respond(); + let on_image_available = self.on_image_available.as_ref().unwrap().respond(); let url = (*url).clone(); do task::spawn { let (response_port, response_chan) = comm::stream(); From c85953deeb3ddc733666f390f6cd5fa3b2a97434 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 26 Nov 2013 12:10:40 -0800 Subject: [PATCH 2/2] net: De-GC the image cache stuff. This is a step on the way toward parallel layout. --- src/components/net/image_cache_task.rs | 25 +++---- src/components/net/local_image_cache.rs | 88 ++++++++++++++----------- src/components/util/url.rs | 5 +- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/src/components/net/image_cache_task.rs b/src/components/net/image_cache_task.rs index bdf7e1d9404..3e06de423c6 100644 --- a/src/components/net/image_cache_task.rs +++ b/src/components/net/image_cache_task.rs @@ -48,22 +48,13 @@ pub enum Msg { Exit(Chan<()>), } +#[deriving(Clone)] pub enum ImageResponseMsg { ImageReady(Arc<~Image>), ImageNotReady, ImageFailed } -impl ImageResponseMsg { - fn clone(&self) -> ImageResponseMsg { - match *self { - ImageReady(ref img) => ImageReady(img.clone()), - ImageNotReady => ImageNotReady, - ImageFailed => ImageFailed, - } - } -} - impl Eq for ImageResponseMsg { fn eq(&self, other: &ImageResponseMsg) -> bool { // FIXME: Bad copies @@ -243,11 +234,11 @@ impl ImageCache { } } - fn set_state(&self, url: Url, state: ImageState) { + fn set_state(&mut self, url: Url, state: ImageState) { self.state_map.insert(url, state); } - fn prefetch(&self, url: Url) { + fn prefetch(&mut self, url: Url) { match self.get_state(url.clone()) { Init => { let to_cache = self.chan.clone(); @@ -278,7 +269,7 @@ impl ImageCache { } } - fn store_prefetched_image_data(&self, url: Url, data: Result, ()>) { + fn store_prefetched_image_data(&mut self, url: Url, data: Result, ()>) { match self.get_state(url.clone()) { Prefetching(next_step) => { match data { @@ -307,7 +298,7 @@ impl ImageCache { } } - fn decode(&self, url: Url) { + fn decode(&mut self, url: Url) { match self.get_state(url.clone()) { Init => fail!(~"decoding image before prefetch"), @@ -350,7 +341,7 @@ impl ImageCache { } } - fn store_image(&self, url: Url, image: Option>) { + fn store_image(&mut self, url: Url, image: Option>) { match self.get_state(url.clone()) { Decoding => { @@ -377,7 +368,7 @@ impl ImageCache { } - fn purge_waiters(&self, url: Url, f: &fn() -> ImageResponseMsg) { + fn purge_waiters(&mut self, url: Url, f: &fn() -> ImageResponseMsg) { match self.wait_map.pop(&url) { Some(waiters) => { for response in waiters.iter() { @@ -399,7 +390,7 @@ impl ImageCache { } } - fn wait_for_image(&self, url: Url, response: Chan) { + fn wait_for_image(&mut self, url: Url, response: Chan) { match self.get_state(url.clone()) { Init => fail!(~"request for image before prefetch"), diff --git a/src/components/net/local_image_cache.rs b/src/components/net/local_image_cache.rs index 12521263a30..f1889ff306b 100644 --- a/src/components/net/local_image_cache.rs +++ b/src/components/net/local_image_cache.rs @@ -34,9 +34,10 @@ pub struct LocalImageCache { priv image_cache_task: ImageCacheTask, priv round_number: uint, priv on_image_available: Option<~ImageResponder:Send>, - priv state_map: UrlMap<@mut ImageState> + priv state_map: UrlMap } +#[deriving(Clone)] struct ImageState { prefetched: bool, decoded: bool, @@ -52,51 +53,62 @@ impl LocalImageCache { self.on_image_available = Some(on_image_available); } - pub fn prefetch(&self, url: &Url) { - let state = self.get_state(url); - if !state.prefetched { - self.image_cache_task.send(Prefetch((*url).clone())); + pub fn prefetch(&mut self, url: &Url) { + { + let state = self.get_state(url); + if state.prefetched { + return + } + state.prefetched = true; } + + self.image_cache_task.send(Prefetch((*url).clone())); } - pub fn decode(&self, url: &Url) { - let state = self.get_state(url); - if !state.decoded { - self.image_cache_task.send(Decode((*url).clone())); + pub fn decode(&mut self, url: &Url) { + { + let state = self.get_state(url); + if state.decoded { + return + } state.decoded = true; } + + self.image_cache_task.send(Decode((*url).clone())); } // FIXME: Should return a Future - pub fn get_image(&self, url: &Url) -> Port { - let state = self.get_state(url); + pub fn get_image(&mut self, url: &Url) -> Port { + { + let state = self.get_state(url); - // Save the previous round number for comparison - let last_round = state.last_request_round; - // Set the current round number for this image - state.last_request_round = self.round_number; + // Save the previous round number for comparison + let last_round = state.last_request_round; + // Set the current round number for this image + state.last_request_round = self.round_number; - match state.last_response { - ImageReady(ref image) => { - let (port, chan) = comm::stream(); - chan.send(ImageReady(image.clone())); - return port; - } - ImageNotReady => { - if last_round == self.round_number { + match state.last_response { + ImageReady(ref image) => { let (port, chan) = comm::stream(); - chan.send(ImageNotReady); + chan.send(ImageReady(image.clone())); + return port; + } + ImageNotReady => { + if last_round == self.round_number { + let (port, chan) = comm::stream(); + chan.send(ImageNotReady); + return port; + } else { + // We haven't requested the image from the + // remote cache this round + } + } + ImageFailed => { + let (port, chan) = comm::stream(); + chan.send(ImageFailed); return port; - } else { - // We haven't requested the image from the - // remote cache this round } - } - ImageFailed => { - let (port, chan) = comm::stream(); - chan.send(ImageFailed); - return port; } } @@ -130,24 +142,24 @@ impl LocalImageCache { ImageNotReady => ImageNotReady, ImageFailed => ImageFailed }; - state.last_response = response_copy; + self.get_state(url).last_response = response_copy; let (port, chan) = comm::stream(); chan.send(response); return port; } - fn get_state(&self, url: &Url) -> @mut ImageState { - let state = do self.state_map.find_or_insert_with(url.clone()) |_| { - let new_state = @mut ImageState { + fn get_state<'a>(&'a mut self, url: &Url) -> &'a mut ImageState { + let state = self.state_map.find_or_insert_with(url.clone(), |_| { + let new_state = ImageState { prefetched: false, decoded: false, last_request_round: 0, last_response: ImageNotReady }; new_state - }; - *state // Unborrowing the state + }); + state } } diff --git a/src/components/util/url.rs b/src/components/util/url.rs index 29385decd58..bf796c02c19 100644 --- a/src/components/util/url.rs +++ b/src/components/util/url.rs @@ -147,8 +147,9 @@ mod make_url_tests { } -pub type UrlMap = @mut HashMap; +pub type UrlMap = HashMap; pub fn url_map() -> UrlMap { - @mut HashMap::new() + HashMap::new() } +