}
all_images[pathname] = load_image_raw(pathname);
- timespec first_modified = all_images[pathname]->last_modified;
- update_threads[pathname] =
- thread(bind(update_thread_func, filename, pathname, first_modified));
+
+ if (!update_thread_started) {
+ update_thread = thread(update_thread_func);
+ update_thread_started = true;
+ }
return all_images[pathname];
}
return image;
}
-// Fire up a thread to update the image every second.
+// Fire up a thread to update all images every second.
// We could do inotify, but this is good enough for now.
-void ImageInput::update_thread_func(const std::string &filename, const std::string &pathname, const timespec &first_modified)
+void ImageInput::update_thread_func()
{
- char thread_name[16];
- snprintf(thread_name, sizeof(thread_name), "Update_%s", filename.c_str());
- pthread_setname_np(pthread_self(), thread_name);
+ pthread_setname_np(pthread_self(), "Update_Images");
- timespec last_modified = first_modified;
struct stat buf;
for ( ;; ) {
{
unique_lock<mutex> lock(threads_should_quit_mu);
threads_should_quit_modified.wait_for(lock, chrono::seconds(1), []() { return threads_should_quit; });
}
-
if (threads_should_quit) {
return;
}
- if (stat(pathname.c_str(), &buf) != 0) {
- fprintf(stderr, "%s: Couldn't check for new version, leaving the old in place.\n", pathname.c_str());
- continue;
- }
- if (buf.st_mtim.tv_sec == last_modified.tv_sec &&
- buf.st_mtim.tv_nsec == last_modified.tv_nsec) {
- // Not changed.
- continue;
+ // Go through all loaded images and see if they need to be updated.
+ // We do one pass first through the array with no I/O, to avoid
+ // blocking the renderer.
+ vector<pair<string, timespec>> images_to_check;
+ {
+ unique_lock<mutex> lock(all_images_lock);
+ for (const auto &pathname_and_image : all_images) {
+ const string pathname = pathname_and_image.first;
+ const timespec last_modified = pathname_and_image.second->last_modified;
+ images_to_check.emplace_back(pathname, last_modified);
+ }
}
- shared_ptr<const Image> image = load_image_raw(pathname);
- if (image == nullptr) {
- fprintf(stderr, "Couldn't load image, leaving the old in place.\n");
- continue;
+
+ for (const auto &pathname_and_timespec : images_to_check) {
+ const string pathname = pathname_and_timespec.first;
+ const timespec last_modified = pathname_and_timespec.second;
+
+ if (stat(pathname.c_str(), &buf) != 0) {
+ fprintf(stderr, "%s: Couldn't check for new version, leaving the old in place.\n", pathname.c_str());
+ continue;
+ }
+ if (buf.st_mtim.tv_sec == last_modified.tv_sec &&
+ buf.st_mtim.tv_nsec == last_modified.tv_nsec) {
+ // Not changed.
+ continue;
+ }
+
+ shared_ptr<const Image> image = load_image_raw(pathname);
+ if (image == nullptr) {
+ fprintf(stderr, "Couldn't load image, leaving the old in place.\n");
+ continue;
+ }
+
+ unique_lock<mutex> lock(all_images_lock);
+ all_images[pathname] = image;
}
- fprintf(stderr, "Loaded new version of %s from disk.\n", pathname.c_str());
- lock_guard<mutex> lock(all_images_lock);
- all_images[pathname] = image;
- last_modified = image->last_modified;
}
}
threads_should_quit = true;
threads_should_quit_modified.notify_all();
}
- for (auto &it : update_threads) {
- it.second.join();
+
+ lock_guard<mutex> lock(all_images_lock);
+ if (update_thread_started) {
+ update_thread.join();
}
}
mutex ImageInput::all_images_lock;
map<string, shared_ptr<const ImageInput::Image>> ImageInput::all_images;
-map<string, thread> ImageInput::update_threads;
+bool ImageInput::update_thread_started = false;
+thread ImageInput::update_thread;
mutex ImageInput::threads_should_quit_mu;
bool ImageInput::threads_should_quit = false;
condition_variable ImageInput::threads_should_quit_modified;