script: Make the ImageCacheTask use IPC.

This necessitated getting rid of the boxed trait object that was being
be passed between the script task and the image cache task.
This commit is contained in:
Patrick Walton 2015-07-10 20:02:17 -07:00
parent 380de1ba82
commit 82b53d83ff
11 changed files with 102 additions and 61 deletions

View file

@ -3,20 +3,33 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use image::base::Image;
use ipc_channel::ipc::{self, IpcSender};
use url::Url;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender};
/// This is optionally passed to the image cache when requesting
/// and image, and returned to the specified event loop when the
/// image load completes. It is typically used to trigger a reflow
/// and/or repaint.
pub trait ImageResponder : Send {
fn respond(&self, ImageResponse);
#[derive(Deserialize, Serialize)]
pub struct ImageResponder {
sender: IpcSender<ImageResponse>,
}
impl ImageResponder {
pub fn new(sender: IpcSender<ImageResponse>) -> ImageResponder {
ImageResponder {
sender: sender,
}
}
pub fn respond(&self, response: ImageResponse) {
self.sender.send(response).unwrap()
}
}
/// The current state of an image in the cache.
#[derive(PartialEq, Copy, Clone)]
#[derive(PartialEq, Copy, Clone, Deserialize, Serialize)]
pub enum ImageState {
Pending,
LoadError,
@ -24,7 +37,7 @@ pub enum ImageState {
}
/// The returned image.
#[derive(Clone)]
#[derive(Clone, Deserialize, Serialize)]
pub enum ImageResponse {
/// The requested image was loaded.
Loaded(Arc<Image>),
@ -35,34 +48,36 @@ pub enum ImageResponse {
}
/// Channel for sending commands to the image cache.
#[derive(Clone)]
pub struct ImageCacheChan(pub Sender<ImageCacheResult>);
#[derive(Clone, Deserialize, Serialize)]
pub struct ImageCacheChan(pub IpcSender<ImageCacheResult>);
/// The result of an image cache command that is returned to the
/// caller.
#[derive(Deserialize, Serialize)]
pub struct ImageCacheResult {
pub responder: Option<Box<ImageResponder>>,
pub responder: Option<ImageResponder>,
pub image_response: ImageResponse,
}
/// Commands that the image cache understands.
#[derive(Deserialize, Serialize)]
pub enum ImageCacheCommand {
/// Request an image asynchronously from the cache. Supply a channel
/// to receive the result, and optionally an image responder
/// that is passed to the result channel.
RequestImage(Url, ImageCacheChan, Option<Box<ImageResponder>>),
RequestImage(Url, ImageCacheChan, Option<ImageResponder>),
/// Synchronously check the state of an image in the cache.
/// TODO(gw): Profile this on some real world sites and see
/// if it's worth caching the results of this locally in each
/// layout / paint task.
GetImageIfAvailable(Url, UsePlaceholder, Sender<Result<Arc<Image>, ImageState>>),
GetImageIfAvailable(Url, UsePlaceholder, IpcSender<Result<Arc<Image>, ImageState>>),
/// Clients must wait for a response before shutting down the ResourceTask
Exit(Sender<()>),
Exit(IpcSender<()>),
}
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
pub enum UsePlaceholder {
No,
Yes,
@ -70,16 +85,16 @@ pub enum UsePlaceholder {
/// The client side of the image cache task. This can be safely cloned
/// and passed to different tasks.
#[derive(Clone)]
#[derive(Clone, Deserialize, Serialize)]
pub struct ImageCacheTask {
chan: Sender<ImageCacheCommand>,
chan: IpcSender<ImageCacheCommand>,
}
/// The public API for the image cache task.
impl ImageCacheTask {
/// Construct a new image cache
pub fn new(chan: Sender<ImageCacheCommand>) -> ImageCacheTask {
pub fn new(chan: IpcSender<ImageCacheCommand>) -> ImageCacheTask {
ImageCacheTask {
chan: chan,
}
@ -89,7 +104,7 @@ impl ImageCacheTask {
pub fn request_image(&self,
url: Url,
result_chan: ImageCacheChan,
responder: Option<Box<ImageResponder>>) {
responder: Option<ImageResponder>) {
let msg = ImageCacheCommand::RequestImage(url, result_chan, responder);
self.chan.send(msg).unwrap();
}
@ -97,7 +112,7 @@ impl ImageCacheTask {
/// Get the current state of an image. See ImageCacheCommand::GetImageIfAvailable.
pub fn get_image_if_available(&self, url: Url, use_placeholder: UsePlaceholder)
-> Result<Arc<Image>, ImageState> {
let (sender, receiver) = channel();
let (sender, receiver) = ipc::channel().unwrap();
let msg = ImageCacheCommand::GetImageIfAvailable(url, use_placeholder, sender);
self.chan.send(msg).unwrap();
receiver.recv().unwrap()
@ -105,7 +120,7 @@ impl ImageCacheTask {
/// Shutdown the image cache task.
pub fn exit(&self) {
let (response_chan, response_port) = channel();
let (response_chan, response_port) = ipc::channel().unwrap();
self.chan.send(ImageCacheCommand::Exit(response_chan)).unwrap();
response_port.recv().unwrap();
}