aboutsummaryrefslogtreecommitdiffstats
path: root/components/net_traits/image_cache_thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/net_traits/image_cache_thread.rs')
-rw-r--r--components/net_traits/image_cache_thread.rs103
1 files changed, 40 insertions, 63 deletions
diff --git a/components/net_traits/image_cache_thread.rs b/components/net_traits/image_cache_thread.rs
index 4fb7aedee04..a000bd8b6bc 100644
--- a/components/net_traits/image_cache_thread.rs
+++ b/components/net_traits/image_cache_thread.rs
@@ -13,27 +13,45 @@ use std::sync::Arc;
/// and/or repaint.
#[derive(Clone, Deserialize, Serialize)]
pub struct ImageResponder {
- sender: IpcSender<ImageResponse>,
+ id: PendingImageId,
+ sender: IpcSender<PendingImageResponse>,
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct PendingImageResponse {
+ pub response: ImageResponse,
+ pub id: PendingImageId,
}
impl ImageResponder {
- pub fn new(sender: IpcSender<ImageResponse>) -> ImageResponder {
+ pub fn new(sender: IpcSender<PendingImageResponse>, id: PendingImageId) -> ImageResponder {
ImageResponder {
sender: sender,
+ id: id,
}
}
pub fn respond(&self, response: ImageResponse) {
- self.sender.send(response).unwrap()
+ // This send can fail if thread waiting for this notification has panicked.
+ // That's not a case that's worth warning about.
+ // TODO(#15501): are there cases in which we should perform cleanup?
+ let _ = self.sender.send(PendingImageResponse {
+ response: response,
+ id: self.id,
+ });
}
}
+/// The unique id for an image that has previously been requested.
+#[derive(Copy, Clone, PartialEq, Eq, Deserialize, Serialize, HeapSizeOf, Hash, Debug)]
+pub struct PendingImageId(pub u64);
+
/// The current state of an image in the cache.
#[derive(PartialEq, Copy, Clone, Deserialize, Serialize)]
pub enum ImageState {
- Pending,
+ Pending(PendingImageId),
LoadError,
- NotRequested,
+ NotRequested(PendingImageId),
}
/// The returned image.
@@ -56,45 +74,19 @@ pub enum ImageOrMetadataAvailable {
MetadataAvailable(ImageMetadata),
}
-/// Channel used by the image cache to send results.
-#[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<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(ServoUrl, ImageCacheChan, Option<ImageResponder>),
-
- /// Requests an image and a "metadata-ready" notification message asynchronously from the
- /// cache. The cache will make an effort to send metadata before the image is completely
- /// loaded. Supply a channel to receive the results, and optionally an image responder
- /// that is passed to the result channel.
- RequestImageAndMetadata(ServoUrl, 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 thread.
- GetImageIfAvailable(ServoUrl, UsePlaceholder, IpcSender<Result<Arc<Image>, ImageState>>),
-
/// Synchronously check the state of an image in the cache. If the image is in a loading
/// state and but its metadata has been made available, it will be sent as a response.
GetImageOrMetadataIfAvailable(ServoUrl, UsePlaceholder, IpcSender<Result<ImageOrMetadataAvailable, ImageState>>),
+ /// Add a new listener for the given pending image.
+ AddListener(PendingImageId, ImageResponder),
+
/// Instruct the cache to store this data as a newly-complete network request and continue
/// decoding the result into pixel data
- StoreDecodeImage(ServoUrl, Vec<u8>),
+ StoreDecodeImage(PendingImageId, Vec<u8>),
/// Clients must wait for a response before shutting down the ResourceThread
Exit(IpcSender<()>),
@@ -122,30 +114,6 @@ impl ImageCacheThread {
}
}
- /// Asynchronously request an image. See ImageCacheCommand::RequestImage.
- pub fn request_image(&self, url: ServoUrl, result_chan: ImageCacheChan, responder: Option<ImageResponder>) {
- let msg = ImageCacheCommand::RequestImage(url, result_chan, responder);
- let _ = self.chan.send(msg);
- }
-
- /// Asynchronously request an image and metadata.
- /// See ImageCacheCommand::RequestImageAndMetadata
- pub fn request_image_and_metadata(&self,
- url: ServoUrl,
- result_chan: ImageCacheChan,
- responder: Option<ImageResponder>) {
- let msg = ImageCacheCommand::RequestImageAndMetadata(url, result_chan, responder);
- let _ = self.chan.send(msg);
- }
-
- /// Get the current state of an image. See ImageCacheCommand::GetImageIfAvailable.
- pub fn find_image(&self, url: ServoUrl, use_placeholder: UsePlaceholder) -> Result<Arc<Image>, ImageState> {
- let (sender, receiver) = ipc::channel().unwrap();
- let msg = ImageCacheCommand::GetImageIfAvailable(url, use_placeholder, sender);
- let _ = self.chan.send(msg);
- try!(receiver.recv().map_err(|_| ImageState::LoadError))
- }
-
/// Get the current state of an image, returning its metadata if available.
/// See ImageCacheCommand::GetImageOrMetadataIfAvailable.
///
@@ -160,14 +128,23 @@ impl ImageCacheThread {
try!(receiver.recv().map_err(|_| ImageState::LoadError))
}
- /// Decode the given image bytes and cache the result for the given URL.
- pub fn store_complete_image_bytes(&self, url: ServoUrl, image_data: Vec<u8>) {
- let msg = ImageCacheCommand::StoreDecodeImage(url, image_data);
- let _ = self.chan.send(msg);
+ /// Add a new listener for the given pending image id. If the image is already present,
+ /// the responder will still receive the expected response.
+ pub fn add_listener(&self, id: PendingImageId, responder: ImageResponder) {
+ let msg = ImageCacheCommand::AddListener(id, responder);
+ self.chan.send(msg).expect("Image cache thread is not available");
+ }
+
+ /// Decode the given image bytes and cache the result for the given pending ID.
+ pub fn store_complete_image_bytes(&self, id: PendingImageId, image_data: Vec<u8>) {
+ let msg = ImageCacheCommand::StoreDecodeImage(id, image_data);
+ self.chan.send(msg).expect("Image cache thread is not available");
}
/// Shutdown the image cache thread.
pub fn exit(&self) {
+ // If the image cache is not available when we're trying to shut it down,
+ // that is not worth warning about.
let (response_chan, response_port) = ipc::channel().unwrap();
let _ = self.chan.send(ImageCacheCommand::Exit(response_chan));
let _ = response_port.recv();