From 878beb16ad10d1e1e44d51f3841d44a6836bb4e9 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 19 Oct 2020 14:56:53 +0200 Subject: Fix threading crash (assigning to a new thread before the thread has died), caching of images smaller than thumbnail target size --- include/ImageViewer.hpp | 1 + src/AsyncImageLoader.cpp | 16 +++++++++++----- src/ImageViewer.cpp | 9 ++++++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/ImageViewer.hpp b/include/ImageViewer.hpp index 2cf3ac2..ea53558 100644 --- a/include/ImageViewer.hpp +++ b/include/ImageViewer.hpp @@ -47,6 +47,7 @@ namespace QuickMedia { class ImageViewer { public: ImageViewer(MangaImagesPage *manga_images_page, const std::string &content_title, const std::string &chapter_title, int current_page, const Path &chapter_cache_dir, sf::Font *font); + ~ImageViewer(); ImageViewerAction draw(sf::RenderWindow &window); // Returns page as 1 indexed int get_focused_page() const; diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index 2f0f869..05c6a7e 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -103,7 +103,7 @@ namespace QuickMedia { } AsyncImageLoader::AsyncImageLoader() { - for(size_t i = 0; i < NUM_IMAGE_LOAD_THREADS; ++i) { + for(int i = 0; i < NUM_IMAGE_LOAD_THREADS; ++i) { loading_image[i] = false; } @@ -147,6 +147,12 @@ namespace QuickMedia { load_image_cv.notify_one(); } load_image_thread.join(); + + // TODO: Find a way to kill the threads instead. We need to do this right now because creating a new thread before the last one has died causes a crash + for(size_t i = 0; i < NUM_IMAGE_LOAD_THREADS; ++i) { + if(download_image_thread[i].joinable()) + download_image_thread[i].join(); + } } void AsyncImageLoader::load_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size, bool use_tor, std::shared_ptr thumbnail_data) { @@ -182,6 +188,8 @@ namespace QuickMedia { loading_image[free_index] = true; thumbnail_data->loading_state = LoadingState::LOADING; + if(download_image_thread[free_index].joinable()) + download_image_thread[free_index].join(); // TODO: Keep the thread running and use conditional variable instead to sleep until a new image should be loaded. Same in ImageViewer. download_image_thread[free_index] = std::thread([this, free_index, thumbnail_path, url, local, resize_target_size, thumbnail_data, use_tor]() mutable { @@ -199,9 +207,8 @@ namespace QuickMedia { return; } } else { - Path download_path = thumbnail_path; - download_path.append(".orig"); - if(download_to_file(url, download_path.data, {}, use_tor, true) != DownloadResult::OK || !thumbnail_data->image->loadFromFile(download_path.data)) { + // Use the same path as the thumbnail path, since it wont be overwritten if the image is smaller than the thumbnail target size + if(download_to_file(url, thumbnail_path.data, {}, use_tor, true) != DownloadResult::OK || !thumbnail_data->image->loadFromFile(thumbnail_path.data)) { thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; loading_image[free_index] = false; return; @@ -216,7 +223,6 @@ namespace QuickMedia { loading_image[free_index] = false; return; }); - download_image_thread[free_index].detach(); } int AsyncImageLoader::get_free_load_index() const { diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp index a8e6041..fc7b758 100644 --- a/src/ImageViewer.cpp +++ b/src/ImageViewer.cpp @@ -35,11 +35,19 @@ namespace QuickMedia { has_size_vertical_cursor = size_vertical_cursor.loadFromSystem(sf::Cursor::SizeVertical); } + ImageViewer::~ImageViewer() { + // TODO: Remove + if(image_loader_thread.joinable()) + image_loader_thread.join(); + } + void ImageViewer::load_image_async(const Path &path, std::shared_ptr image_data) { image_data->image_status = ImageStatus::LOADING; image_data->texture.setSmooth(true); assert(!loading_image); loading_image = true; + if(image_loader_thread.joinable()) + image_loader_thread.join(); image_loader_thread = std::thread([this, image_data, path]() mutable { auto image = std::make_unique(); if(image->loadFromFile(path.data)) { @@ -50,7 +58,6 @@ namespace QuickMedia { } loading_image = false; }); - image_loader_thread.detach(); } bool ImageViewer::render_page(sf::RenderWindow &window, int page, double offset_y) { -- cgit v1.2.3