mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
auto merge of #1313 : pcwalton/servo/parallel-layout, r=larsbergstrom
This is one small step toward parallel layout. r? @larsbergstrom
This commit is contained in:
commit
a76f761ed3
4 changed files with 67 additions and 63 deletions
|
@ -675,15 +675,15 @@ impl LayoutTask {
|
||||||
// to the script task, and ultimately cause the image to be
|
// 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
|
// re-requested. We probably don't need to go all the way back to
|
||||||
// the script task for this.
|
// 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
|
// This has a crazy signature because the image cache needs to
|
||||||
// make multiple copies of the callback, and the dom event
|
// make multiple copies of the callback, and the dom event
|
||||||
// channel is not a copyable type, so this is actually a
|
// channel is not a copyable type, so this is actually a
|
||||||
// little factory to produce callbacks
|
// little factory to produce callbacks
|
||||||
@LayoutImageResponder {
|
~LayoutImageResponder {
|
||||||
id: self.id.clone(),
|
id: self.id.clone(),
|
||||||
script_chan: self.script_chan.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
|
/// Handles a message to destroy layout data. Layout data must be destroyed on *this* task
|
||||||
|
|
|
@ -48,22 +48,13 @@ pub enum Msg {
|
||||||
Exit(Chan<()>),
|
Exit(Chan<()>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub enum ImageResponseMsg {
|
pub enum ImageResponseMsg {
|
||||||
ImageReady(Arc<~Image>),
|
ImageReady(Arc<~Image>),
|
||||||
ImageNotReady,
|
ImageNotReady,
|
||||||
ImageFailed
|
ImageFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageResponseMsg {
|
|
||||||
fn clone(&self) -> ImageResponseMsg {
|
|
||||||
match *self {
|
|
||||||
ImageReady(ref img) => ImageReady(img.clone()),
|
|
||||||
ImageNotReady => ImageNotReady,
|
|
||||||
ImageFailed => ImageFailed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for ImageResponseMsg {
|
impl Eq for ImageResponseMsg {
|
||||||
fn eq(&self, other: &ImageResponseMsg) -> bool {
|
fn eq(&self, other: &ImageResponseMsg) -> bool {
|
||||||
// FIXME: Bad copies
|
// 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);
|
self.state_map.insert(url, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefetch(&self, url: Url) {
|
fn prefetch(&mut self, url: Url) {
|
||||||
match self.get_state(url.clone()) {
|
match self.get_state(url.clone()) {
|
||||||
Init => {
|
Init => {
|
||||||
let to_cache = self.chan.clone();
|
let to_cache = self.chan.clone();
|
||||||
|
@ -278,7 +269,7 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_prefetched_image_data(&self, url: Url, data: Result<Cell<~[u8]>, ()>) {
|
fn store_prefetched_image_data(&mut self, url: Url, data: Result<Cell<~[u8]>, ()>) {
|
||||||
match self.get_state(url.clone()) {
|
match self.get_state(url.clone()) {
|
||||||
Prefetching(next_step) => {
|
Prefetching(next_step) => {
|
||||||
match data {
|
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()) {
|
match self.get_state(url.clone()) {
|
||||||
Init => fail!(~"decoding image before prefetch"),
|
Init => fail!(~"decoding image before prefetch"),
|
||||||
|
|
||||||
|
@ -350,7 +341,7 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_image(&self, url: Url, image: Option<Arc<~Image>>) {
|
fn store_image(&mut self, url: Url, image: Option<Arc<~Image>>) {
|
||||||
|
|
||||||
match self.get_state(url.clone()) {
|
match self.get_state(url.clone()) {
|
||||||
Decoding => {
|
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) {
|
match self.wait_map.pop(&url) {
|
||||||
Some(waiters) => {
|
Some(waiters) => {
|
||||||
for response in waiters.iter() {
|
for response in waiters.iter() {
|
||||||
|
@ -399,7 +390,7 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
fn wait_for_image(&mut self, url: Url, response: Chan<ImageResponseMsg>) {
|
||||||
match self.get_state(url.clone()) {
|
match self.get_state(url.clone()) {
|
||||||
Init => fail!(~"request for image before prefetch"),
|
Init => fail!(~"request for image before prefetch"),
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,11 @@ pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
||||||
pub struct LocalImageCache {
|
pub struct LocalImageCache {
|
||||||
priv image_cache_task: ImageCacheTask,
|
priv image_cache_task: ImageCacheTask,
|
||||||
priv round_number: uint,
|
priv round_number: uint,
|
||||||
priv on_image_available: Option<@ImageResponder>,
|
priv on_image_available: Option<~ImageResponder:Send>,
|
||||||
priv state_map: UrlMap<@mut ImageState>
|
priv state_map: UrlMap<ImageState>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
struct ImageState {
|
struct ImageState {
|
||||||
prefetched: bool,
|
prefetched: bool,
|
||||||
decoded: bool,
|
decoded: bool,
|
||||||
|
@ -47,56 +48,67 @@ struct ImageState {
|
||||||
impl LocalImageCache {
|
impl LocalImageCache {
|
||||||
/// The local cache will only do a single remote request for a given
|
/// 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
|
/// 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.round_number += 1;
|
||||||
self.on_image_available = Some(on_image_available);
|
self.on_image_available = Some(on_image_available);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefetch(&self, url: &Url) {
|
pub fn prefetch(&mut self, url: &Url) {
|
||||||
let state = self.get_state(url);
|
{
|
||||||
if !state.prefetched {
|
let state = self.get_state(url);
|
||||||
self.image_cache_task.send(Prefetch((*url).clone()));
|
if state.prefetched {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
state.prefetched = true;
|
state.prefetched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.image_cache_task.send(Prefetch((*url).clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(&self, url: &Url) {
|
pub fn decode(&mut self, url: &Url) {
|
||||||
let state = self.get_state(url);
|
{
|
||||||
if !state.decoded {
|
let state = self.get_state(url);
|
||||||
self.image_cache_task.send(Decode((*url).clone()));
|
if state.decoded {
|
||||||
|
return
|
||||||
|
}
|
||||||
state.decoded = true;
|
state.decoded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.image_cache_task.send(Decode((*url).clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Should return a Future
|
// FIXME: Should return a Future
|
||||||
pub fn get_image(&self, url: &Url) -> Port<ImageResponseMsg> {
|
pub fn get_image(&mut self, url: &Url) -> Port<ImageResponseMsg> {
|
||||||
let state = self.get_state(url);
|
{
|
||||||
|
let state = self.get_state(url);
|
||||||
|
|
||||||
// Save the previous round number for comparison
|
// Save the previous round number for comparison
|
||||||
let last_round = state.last_request_round;
|
let last_round = state.last_request_round;
|
||||||
// Set the current round number for this image
|
// Set the current round number for this image
|
||||||
state.last_request_round = self.round_number;
|
state.last_request_round = self.round_number;
|
||||||
|
|
||||||
match state.last_response {
|
match state.last_response {
|
||||||
ImageReady(ref image) => {
|
ImageReady(ref image) => {
|
||||||
let (port, chan) = comm::stream();
|
|
||||||
chan.send(ImageReady(image.clone()));
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
ImageNotReady => {
|
|
||||||
if last_round == self.round_number {
|
|
||||||
let (port, chan) = comm::stream();
|
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;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +125,7 @@ impl LocalImageCache {
|
||||||
// on the image to load and triggering layout
|
// on the image to load and triggering layout
|
||||||
let image_cache_task = self.image_cache_task.clone();
|
let image_cache_task = self.image_cache_task.clone();
|
||||||
assert!(self.on_image_available.is_some());
|
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();
|
let url = (*url).clone();
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
let (response_port, response_chan) = comm::stream();
|
let (response_port, response_chan) = comm::stream();
|
||||||
|
@ -130,24 +142,24 @@ impl LocalImageCache {
|
||||||
ImageNotReady => ImageNotReady,
|
ImageNotReady => ImageNotReady,
|
||||||
ImageFailed => ImageFailed
|
ImageFailed => ImageFailed
|
||||||
};
|
};
|
||||||
state.last_response = response_copy;
|
self.get_state(url).last_response = response_copy;
|
||||||
|
|
||||||
let (port, chan) = comm::stream();
|
let (port, chan) = comm::stream();
|
||||||
chan.send(response);
|
chan.send(response);
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_state(&self, url: &Url) -> @mut ImageState {
|
fn get_state<'a>(&'a mut self, url: &Url) -> &'a mut ImageState {
|
||||||
let state = do self.state_map.find_or_insert_with(url.clone()) |_| {
|
let state = self.state_map.find_or_insert_with(url.clone(), |_| {
|
||||||
let new_state = @mut ImageState {
|
let new_state = ImageState {
|
||||||
prefetched: false,
|
prefetched: false,
|
||||||
decoded: false,
|
decoded: false,
|
||||||
last_request_round: 0,
|
last_request_round: 0,
|
||||||
last_response: ImageNotReady
|
last_response: ImageNotReady
|
||||||
};
|
};
|
||||||
new_state
|
new_state
|
||||||
};
|
});
|
||||||
*state // Unborrowing the state
|
state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,8 +147,9 @@ mod make_url_tests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UrlMap<T> = @mut HashMap<Url, T>;
|
pub type UrlMap<T> = HashMap<Url, T>;
|
||||||
|
|
||||||
pub fn url_map<T: Clone + 'static>() -> UrlMap<T> {
|
pub fn url_map<T: Clone + 'static>() -> UrlMap<T> {
|
||||||
@mut HashMap::new()
|
HashMap::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue