Remove timeout code as there exists no general way to stop worker threads

This commit is contained in:
Fin Christensen 2019-08-20 15:20:45 +02:00
parent 3c82188135
commit de45635057
No known key found for this signature in database
GPG Key ID: 1C295651D0424BF1
7 changed files with 120 additions and 167 deletions

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab
[{*.json,*.yml}]
indent_size = 2

View File

@ -2,3 +2,11 @@ language: rust
rust:
- stable
- nightly
script:
- RUST_CHAIN=$TRAVIS_RUST_VERSION ./scripts/ci-build.sh
# do not use deploy here as deploy scripts are not executed for failed builds
after_script:
- >
test "$TRAVIS_PULL_REQUEST" = false &&
test "$TRAVIS_BRANCH" = master &&
GITHUB_REPO_SLUG="$TRAVIS_REPO_SLUG" ./scripts/deploy-badges.sh

View File

@ -1,28 +0,0 @@
use cursive::{
views::{Dialog, TextView},
Cursive,
};
use cursive_async_view::AsyncView;
use std::time::Duration;
fn main() {
cursive::logger::init();
let mut siv = Cursive::default();
// We can quit by pressing `q`
siv.add_global_callback('q', Cursive::quit);
let async_view = AsyncView::new(&siv, move || {
std::thread::sleep(std::time::Duration::from_secs(10));
TextView::new("Yay!\n\nThe content has loaded! ")
})
.with_width(40)
.with_timeout(Duration::from_secs(5))
.with_timeout_view(TextView::new("Oh no, the content has not loaded :("));
let dialog = Dialog::around(async_view).button("Ok", |s| s.quit());
siv.add_layer(dialog);
siv.run();
}

45
scripts/ci-build.sh Executable file
View File

@ -0,0 +1,45 @@
#! /bin/sh
die() {
printf "\e[31:1mError: %s\e[0m\n" "$1" >&2
exit 1
}
(
cd "$(git rev-parse --show-toplevel)" || die "cannot find project root"
# Badges!
mkdir -p ./target/shields
if cargo "+${RUST_CHAIN}" --color=always build --all-targets; then
cat <<EOF > "./target/shields/$RUST_CHAIN-build.json"
{
"color": "brightgreen",
"isError": true,
"label": "$RUST_CHAIN build",
"message": "passing",
"schemaVersion": 1
}
EOF
else
PRV_EXIT=$?
cat <<EOF > "./target/shields/$RUST_CHAIN-build.json"
{
"color": "red",
"isError": true,
"label": "$RUST_CHAIN build",
"message": "failed",
"schemaVersion": 1
}
EOF
exit $PRV_EXIT
fi
cargo "+${RUST_CHAIN}" --color=always test --no-fail-fast
exitcode=$?
# create badge for `cargo test`
cargo "+${RUST_CHAIN}" test --no-fail-fast -- -Z unstable-options --format json | \
jq -s -f ./scripts/shields-from-tests.jq > ./target/shields/cargo-test.json
exit $exitcode
)

50
scripts/deploy-badges.sh Executable file
View File

@ -0,0 +1,50 @@
#! /bin/sh
die() {
printf "\e[31:1mError: %s\e[0m\n" "$1" >&2
exit 1
}
if [ -z "$GITHUB_USERNAME" ]
then
die "the GITHUB_USERNAME environment variable is not set"
fi
if [ -z "$GITHUB_TOKEN" ]
then
die "the GITHUB_TOKEN environment variable is not set"
fi
if [ -z "$GITHUB_REPO_SLUG" ]
then
die "the GITHUB_REPO_SLUG environment variable is not set"
fi
(
cd "$(git rev-parse --show-toplevel)/target/shields" || die "cannot find project root!"
repo="https://${GITHUB_USERNAME}:${GITHUB_TOKEN}@github.com/${GITHUB_REPO_SLUG}.git"
tmp_dir=$(mktemp -d -t cursive-async-view-deploy-XXXXXXXX)
try=0
while :; do
git clone --branch gh-pages "$repo" "$tmp_dir"
cp -ar ./* "$tmp_dir"
(
cd "$tmp_dir" || die "failed to enter temporary directory"
git add -A
git commit -m "Travis CI badge deployment"
git push
)
result=$?
rm -rf "$tmp_dir"
if [ "$result" -eq 0 ] || [ "$try" -ge 5 ]
then
break
fi
try=$((try + 1))
done
)

View File

@ -1,5 +1,5 @@
use std::thread;
use std::time::{Duration, Instant};
use std::time::Duration;
use crossbeam::channel::{self, Receiver};
use cursive::direction::Direction;
@ -58,15 +58,11 @@ pub struct AsyncView<T: View + Send> {
animation_fn: Box<dyn Fn(usize, usize, usize) -> AnimationFrame + 'static>,
width: Option<usize>,
height: Option<usize>,
timeout: Option<Duration>,
start_time: Instant,
timeout_view: Box<dyn View + 'static>,
pos: usize,
rx: Receiver<T>,
}
impl<T: View + Send> AsyncView<T> {
// TODO: add timeout parameter
pub fn new<F>(siv: &Cursive, creator: F) -> Self
where
F: FnOnce() -> T + Send + 'static,
@ -110,28 +106,11 @@ impl<T: View + Send> AsyncView<T> {
animation_fn: Box::new(default_animation),
width: None,
height: None,
timeout: None,
start_time: Instant::now(),
timeout_view: Box::new(TextView::new("View timed out.")),
pos: 0,
rx,
}
}
pub fn with_timeout(self, timeout: Duration) -> Self {
Self {
timeout: Some(timeout),
..self
}
}
pub fn with_timeout_view(self, timeout_view: T) -> Self {
Self {
timeout_view: Box::new(timeout_view),
..self
}
}
pub fn with_width(self, width: usize) -> Self {
Self {
width: Some(width),
@ -161,18 +140,6 @@ impl<T: View + Send> AsyncView<T> {
}
}
pub fn set_timeout(&mut self, timeout: Duration) {
self.timeout = Some(timeout);
}
pub fn inherit_timeout(&mut self) {
self.timeout = None;
}
pub fn set_timeout_view(&mut self, timeout_view: T) {
self.timeout_view = Box::new(timeout_view);
}
pub fn set_width(&mut self, width: usize) {
self.width = Some(width);
}
@ -195,22 +162,10 @@ impl<T: View + Send> AsyncView<T> {
{
self.animation_fn = Box::new(animation_fn);
}
fn is_timedout(&self) -> bool {
if let Some(timeout) = self.timeout {
Instant::now().duration_since(self.start_time) > timeout
} else {
false
}
}
}
impl<T: View + Send + Sized> View for AsyncView<T> {
fn draw(&self, printer: &Printer) {
if self.is_timedout() {
self.timeout_view.draw(printer);
return;
}
match self.view {
Some(ref view) => view.draw(printer),
None => self.loading.draw(printer),
@ -218,10 +173,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn layout(&mut self, vec: Vec2) {
if self.is_timedout() {
self.timeout_view.layout(vec);
return;
}
match self.view {
Some(ref mut view) => view.layout(vec),
None => self.loading.layout(vec),
@ -236,10 +187,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
if self.is_timedout() {
return self.timeout_view.required_size(constraint);
}
if self.view.is_none() {
match self.rx.try_recv() {
Ok(view) => self.view = Some(view),
@ -266,9 +213,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn on_event(&mut self, ev: Event) -> EventResult {
if self.is_timedout() {
return self.timeout_view.on_event(ev);
}
match self.view {
Some(ref mut view) => view.on_event(ev),
None => self.loading.on_event(ev),
@ -276,9 +220,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn call_on_any<'a>(&mut self, sel: &Selector, cb: AnyCb<'a>) {
if self.is_timedout() {
return self.timeout_view.call_on_any(sel, cb);
}
match self.view {
Some(ref mut view) => view.call_on_any(sel, cb),
None => self.loading.call_on_any(sel, cb),
@ -286,9 +227,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn focus_view(&mut self, sel: &Selector) -> Result<(), ()> {
if self.is_timedout() {
return self.timeout_view.focus_view(sel);
}
match self.view {
Some(ref mut view) => view.focus_view(sel),
None => self.loading.focus_view(sel),
@ -296,9 +234,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn take_focus(&mut self, source: Direction) -> bool {
if self.is_timedout() {
return self.timeout_view.take_focus(source);
}
match self.view {
Some(ref mut view) => view.take_focus(source),
None => self.loading.take_focus(source),
@ -306,9 +241,6 @@ impl<T: View + Send + Sized> View for AsyncView<T> {
}
fn important_area(&self, view_size: Vec2) -> Rect {
if self.is_timedout() {
return self.timeout_view.important_area(view_size);
}
match self.view {
Some(ref view) => view.important_area(view_size),
None => self.loading.important_area(view_size),

View File

@ -1,5 +1,4 @@
use std::thread;
use std::time::{Duration, Instant};
use crossbeam::channel::{self, Receiver, Sender};
use cursive::direction::Direction;
@ -35,9 +34,6 @@ pub struct AsyncProgressView<T: View + Send> {
progress_fn: Box<dyn Fn(usize, usize, f32) -> StyledString + 'static>,
width: Option<usize>,
height: Option<usize>,
timeout: Option<Duration>,
start_time: Instant,
timeout_view: Box<dyn View + 'static>,
view_rx: Receiver<T>,
update_rx: Receiver<f32>,
}
@ -84,9 +80,6 @@ impl<T: View + Send + Sized> AsyncProgressView<T> {
view: None,
loading: TextView::new(""),
progress_fn: Box::new(default_progress),
timeout: None,
start_time: Instant::now(),
timeout_view: Box::new(TextView::new("View has timed out.")),
width: None,
height: None,
view_rx,
@ -94,20 +87,6 @@ impl<T: View + Send + Sized> AsyncProgressView<T> {
}
}
pub fn with_timeout(self, timeout: Duration) -> Self {
Self {
timeout: Some(timeout),
..self
}
}
pub fn with_timeout_view(self, timeout_view: T) -> Self {
Self {
timeout_view: Box::new(timeout_view),
..self
}
}
pub fn with_width(self, width: usize) -> Self {
Self {
width: Some(width),
@ -132,18 +111,6 @@ impl<T: View + Send + Sized> AsyncProgressView<T> {
}
}
pub fn set_timeout(&mut self, timeout: Duration) {
self.timeout = Some(timeout);
}
pub fn inherit_timeout(&mut self) {
self.timeout = None;
}
pub fn set_timeout_view(&mut self, timeout_view: T) {
self.timeout_view = Box::new(timeout_view);
}
pub fn set_width(&mut self, width: usize) {
self.width = Some(width);
}
@ -166,22 +133,10 @@ impl<T: View + Send + Sized> AsyncProgressView<T> {
{
self.progress_fn = Box::new(progress_fn);
}
fn is_timedout(&self) -> bool {
if let Some(timeout) = self.timeout {
Instant::now().duration_since(self.start_time) > timeout
} else {
false
}
}
}
impl<T: View + Send + Sized> View for AsyncProgressView<T> {
fn draw(&self, printer: &Printer) {
if self.is_timedout() {
self.timeout_view.draw(printer);
return;
}
match self.view {
Some(ref view) => view.draw(printer),
None => self.loading.draw(printer),
@ -189,10 +144,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn layout(&mut self, vec: Vec2) {
if self.is_timedout() {
self.timeout_view.layout(vec);
return;
}
match self.view {
Some(ref mut view) => view.layout(vec),
None => self.loading.layout(vec),
@ -200,9 +151,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn needs_relayout(&self) -> bool {
if self.is_timedout() {
return self.timeout_view.needs_relayout();
}
match self.view {
Some(ref view) => view.needs_relayout(),
None => true,
@ -210,9 +158,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
if self.is_timedout() {
return self.timeout_view.required_size(constraint);
}
if self.view.is_none() {
match self.view_rx.try_recv() {
Ok(view) => self.view = Some(view),
@ -236,9 +181,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn on_event(&mut self, ev: Event) -> EventResult {
if self.is_timedout() {
return self.timeout_view.on_event(ev);
}
match self.view {
Some(ref mut view) => view.on_event(ev),
None => self.loading.on_event(ev),
@ -246,9 +188,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn call_on_any<'a>(&mut self, sel: &Selector, cb: AnyCb<'a>) {
if self.is_timedout() {
return self.timeout_view.call_on_any(sel, cb);
}
match self.view {
Some(ref mut view) => view.call_on_any(sel, cb),
None => self.loading.call_on_any(sel, cb),
@ -256,9 +195,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn focus_view(&mut self, sel: &Selector) -> Result<(), ()> {
if self.is_timedout() {
return self.timeout_view.focus_view(sel);
}
match self.view {
Some(ref mut view) => view.focus_view(sel),
None => self.loading.focus_view(sel),
@ -266,9 +202,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn take_focus(&mut self, source: Direction) -> bool {
if self.is_timedout() {
return self.timeout_view.take_focus(source);
}
match self.view {
Some(ref mut view) => view.take_focus(source),
None => self.loading.take_focus(source),
@ -276,9 +209,6 @@ impl<T: View + Send + Sized> View for AsyncProgressView<T> {
}
fn important_area(&self, view_size: Vec2) -> Rect {
if self.is_timedout() {
return self.timeout_view.important_area(view_size);
}
match self.view {
Some(ref view) => view.important_area(view_size),
None => self.loading.important_area(view_size),