Implement cancellation listener for cancelling network requests

This commit is contained in:
Ravi Shankar 2015-11-07 18:48:37 +05:30
parent 92f9e58310
commit 10f5584f78
11 changed files with 191 additions and 53 deletions

View file

@ -5,7 +5,8 @@
use mime_classifier::MIMEClassifier;
use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata};
use resource_task::{ProgressSender, send_error, start_sending_sniffed, start_sending_sniffed_opt};
use resource_task::{CancellationListener, ProgressSender};
use resource_task::{send_error, start_sending_sniffed, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::error::Error;
use std::fs::File;
@ -21,6 +22,11 @@ enum ReadStatus {
EOF,
}
enum LoadResult {
Cancelled,
Finished,
}
fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
let mut buf = vec![0; READ_SIZE];
match reader.read(&mut buf) {
@ -33,17 +39,24 @@ fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
}
}
fn read_all(reader: &mut File, progress_chan: &ProgressSender)
-> Result<(), String> {
fn read_all(reader: &mut File, progress_chan: &ProgressSender, cancel_listener: &CancellationListener)
-> Result<LoadResult, String> {
loop {
if cancel_listener.is_cancelled() {
return Ok(LoadResult::Cancelled);
}
match try!(read_block(reader)) {
ReadStatus::Partial(buf) => progress_chan.send(Payload(buf)).unwrap(),
ReadStatus::EOF => return Ok(()),
ReadStatus::EOF => return Ok(LoadResult::Finished),
}
}
}
pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc<MIMEClassifier>) {
pub fn factory(load_data: LoadData,
senders: LoadConsumer,
classifier: Arc<MIMEClassifier>,
cancel_listener: CancellationListener) {
let url = load_data.url;
assert!(&*url.scheme == "file");
spawn_named("file_loader".to_owned(), move || {
@ -52,14 +65,22 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc<MIMEC
Ok(file_path) => {
match File::open(&file_path) {
Ok(ref mut reader) => {
if cancel_listener.is_cancelled() {
return;
}
match read_block(reader) {
Ok(ReadStatus::Partial(buf)) => {
let metadata = Metadata::default(url);
let progress_chan = start_sending_sniffed(senders, metadata,
classifier, &buf);
progress_chan.send(Payload(buf)).unwrap();
let res = read_all(reader, &progress_chan);
let _ = progress_chan.send(Done(res));
let read_result = read_all(reader, &progress_chan, &cancel_listener);
if let Ok(load_result) = read_result {
match load_result {
LoadResult::Cancelled => return,
LoadResult::Finished => progress_chan.send(Done(Ok(()))).unwrap(),
}
}
}
Ok(ReadStatus::EOF) => {
let metadata = Metadata::default(url);