From b66371f95a63265b65360ff80a35419c88863e74 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 2 Oct 2010 19:00:01 -0300 Subject: [PATCH] Move thread class to base lib (the new thread class has a C++0x-like api). --- src/CMakeLists.txt | 4 + src/base/CMakeLists.txt | 3 +- src/base/thread.cpp | 149 +++++++++++++++++++++++++++++++++ src/base/thread.h | 141 +++++++++++++++++++++++++++++++ src/base/thread_unittest.cpp | 56 +++++++++++++ src/commands/cmd_open_file.cpp | 88 +++++++++---------- src/commands/cmd_save_file.cpp | 87 ++++++++++--------- src/commands/fx/effectbg.cpp | 22 +++-- src/errno_unittest.cpp | 10 +-- src/gui/CMakeLists.txt | 1 - src/gui/jinete.h | 1 - src/gui/jthread.cpp | 86 ------------------- src/gui/jthread.h | 15 ---- src/job.cpp | 20 ++--- src/job.h | 6 +- src/widgets/fileview.cpp | 23 ++--- 16 files changed, 472 insertions(+), 240 deletions(-) create mode 100644 src/base/thread.cpp create mode 100644 src/base/thread.h create mode 100644 src/base/thread_unittest.cpp delete mode 100644 src/gui/jthread.cpp delete mode 100644 src/gui/jthread.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88efff26e..437bac430 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,10 @@ if(WIN32) WinMM AdvAPI32 Ole32 ShLwApi Vfw32 WinInet PsApi DDraw DxGuid DSound DInput8) else() + # Pthreads + set(sys_libs ${sys_libs} + pthread) + # Allegro library on Unix like systems find_program(allegro_config "allegro-config") diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index bbfe458f2..20476ad0c 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -8,4 +8,5 @@ add_library(base-lib mutex.cpp path.cpp split_string.cpp - string.cpp) + string.cpp + thread.cpp) diff --git a/src/base/thread.cpp b/src/base/thread.cpp new file mode 100644 index 000000000..be49d3e32 --- /dev/null +++ b/src/base/thread.cpp @@ -0,0 +1,149 @@ +// ASE gui library +// Copyright (C) 2001-2010 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "config.h" + +#include "base/thread.h" + +#ifdef WIN32 + #include + #include +#else + #include // Use pthread library in Unix-like systems +#endif + +namespace { + +#ifdef WIN32 + + static DWORD WINAPI win32_thread_proxy(LPVOID data) + { + base::thread::details::thread_proxy(data); + return 0; + } + +#else + + static void* pthread_thread_proxy(void* data) + { + base::thread::details::thread_proxy(data); + return NULL; + } + +#endif + +} + +base::thread::thread() + : m_native_handle(NULL) + , m_id() +{ +} + +base::thread::~thread() +{ + if (joinable()) + detach(); + +#ifdef USE_PTHREADS + delete (pthread_t*)m_native_handle; +#endif +} + +bool base::thread::joinable() const +{ + return (m_id != this_thread::get_id()); +} + +void base::thread::join() +{ + if (joinable()) { +#ifdef WIN32 + ::WaitForSingleObject(m_native_handle, INFINITE); +#else + ::pthread_join(*(pthread_t*)m_native_handle, NULL); +#endif + detach(); + } +} + +void base::thread::detach() +{ + if (joinable()) { +#ifdef WIN32 + ::CloseHandle(m_native_handle); +#else + ::pthread_detach(*(pthread_t*)m_native_handle); + delete (pthread_t*)m_native_handle; +#endif + m_native_handle = NULL; + m_id = id(); + } +} + +void base::thread::launch_thread(func_wrapper* f) +{ +#ifdef WIN32 + + DWORD native_id; + m_native_handle = ::CreateThread(NULL, 0, win32_thread_proxy, (LPVOID)f, + CREATE_SUSPENDED, &native_id); + m_id.m_native_id = native_id; + ResumeThread(m_native_handle); + +#else + + pthread_t thread; + if (::pthread_create(&thread, NULL, pthread_thread_proxy, f)) + m_native_handle = new pthread_t(thread); + else + m_native_handle = NULL; + +#endif +} + +void base::thread::details::thread_proxy(void* data) +{ + func_wrapper* f = reinterpret_cast(data); + + // Call operator() of func_wrapper class (this is a virtual method). + (*f)(); + + // Delete the data (it was created in the thread() ctor). + delete f; +} + +base::thread::id base::thread::details::get_current_thread_id() +{ +#ifdef WIN32 + return id(::GetCurrentThreadId()); +#else + return id((unsigned int)::pthread_self()); +#endif +} + +base::thread::id base::this_thread::get_id() +{ + return thread::details::get_current_thread_id(); +} + +void base::this_thread::yield() +{ +#ifdef WIN32 + ::Sleep(0); +#else + // TODO +#endif +} + +void base::this_thread::sleep_for(int milliseconds) +{ +#ifdef WIN32 + ::Sleep(milliseconds); +#else + // TODO +#endif +} diff --git a/src/base/thread.h b/src/base/thread.h new file mode 100644 index 000000000..b3a3c49cb --- /dev/null +++ b/src/base/thread.h @@ -0,0 +1,141 @@ +// ASE base library +// Copyright (C) 2001-2010 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#ifndef GUI_THREAD_H_INCLUDED +#define GUI_THREAD_H_INCLUDED + +namespace base { // Based on C++0x threads lib + + class thread { + public: + class details; + class id + { + friend class thread; + friend class details; + + unsigned int m_native_id; + id(unsigned int id) : m_native_id(id) { } + public: + id() : m_native_id(0) { } + bool operator==(const id& y) const { return m_native_id == y.m_native_id; } + bool operator!=(const id& y) const { return m_native_id != y.m_native_id; } + bool operator< (const id& y) const { return m_native_id < y.m_native_id; } + bool operator<=(const id& y) const { return m_native_id <= y.m_native_id; } + bool operator> (const id& y) const { return m_native_id > y.m_native_id; } + bool operator>=(const id& y) const { return m_native_id >= y.m_native_id; } + + // TODO should we replace this with support for iostreams? + //unsigned get_native_id() { return m_native_id; } + }; + + typedef void* native_handle_type; + + public: + + // Create an instance to represent the current thread + thread(); + + // Create a new thread without arguments + template + thread(const Callable& f) { + launch_thread(new func_wrapper0(f)); + } + + // Create a new thread with one argument + template + thread(const Callable& f, A a) { + launch_thread(new func_wrapper1(f, a)); + } + + // Create a new thread with two arguments + template + thread(const Callable& f, A a, B b) { + launch_thread(new func_wrapper2(f, a, b)); + } + + ~thread(); + + bool joinable() const; + void join(); + void detach(); + + id get_id() const { + return m_id; + } + + native_handle_type native_handle() { + return m_native_handle; + } + + class details { + public: + static void thread_proxy(void* data); + static id get_current_thread_id(); + }; + + private: + native_handle_type m_native_handle; + id m_id; + + class func_wrapper { + public: + virtual void operator()() = 0; + }; + + void launch_thread(func_wrapper* f); + + template + class func_wrapper0 : public func_wrapper { + public: + Callable f; + func_wrapper0(const Callable& f) : f(f) { } + void operator()() { f(); } + }; + + template + class func_wrapper1 : public func_wrapper { + public: + Callable f; + A a; + func_wrapper1(const Callable& f, A a) : f(f), a(a) { } + void operator()() { f(a); } + }; + + template + class func_wrapper2 : public func_wrapper { + public: + Callable f; + A a; + B b; + func_wrapper2(const Callable& f, A a, B b) : f(f), a(a), b(b) { } + void operator()() { f(a, b); } + }; + + }; + + namespace this_thread + { + thread::id get_id(); + void yield(); + void sleep_for(int milliseconds); + } + + // This class joins the thread in its destructor. + class thread_guard { + thread& m_thread; + public: + explicit thread_guard(thread& t) : m_thread(t) { } + ~thread_guard() + { + if (m_thread.joinable()) + m_thread.join(); + } + }; + +} + +#endif diff --git a/src/base/thread_unittest.cpp b/src/base/thread_unittest.cpp new file mode 100644 index 000000000..5282d4c1c --- /dev/null +++ b/src/base/thread_unittest.cpp @@ -0,0 +1,56 @@ +// ASE base library +// Copyright (C) 2001-2010 David Capello +// +// This source file is ditributed under a BSD-like license, please +// read LICENSE.txt for more information. + +#include "tests/test.h" + +#include "base/thread.h" + +#include + +using std::cout; +using namespace base; + +static bool flag = false; + +static void func0() { + flag = true; +} + +static void func1(int x) { + flag = true; + EXPECT_EQ(2, x); +} + +static void func2(int x, int y) { + flag = true; + EXPECT_EQ(2, x); + EXPECT_EQ(4, y); +} + +TEST(Thread, WithoutArgs) +{ + flag = false; + thread t(&func0); + t.join(); + EXPECT_TRUE(flag); +} + +TEST(Thread, OneArg) +{ + flag = false; + thread t(&func1, 2); + t.join(); + EXPECT_TRUE(flag); +} + +TEST(Thread, TwoArgs) +{ + flag = false; + thread t(&func2, 2, 4); + t.join(); + EXPECT_TRUE(flag); +} + diff --git a/src/commands/cmd_open_file.cpp b/src/commands/cmd_open_file.cpp index e39be8e36..6afb0089d 100644 --- a/src/commands/cmd_open_file.cpp +++ b/src/commands/cmd_open_file.cpp @@ -18,22 +18,22 @@ #include "config.h" -#include #include +#include -#include "gui/jinete.h" - -#include "ui_context.h" +#include "app.h" +#include "base/thread.h" #include "commands/command.h" #include "commands/params.h" #include "console.h" -#include "app.h" #include "dialogs/filesel.h" #include "file/file.h" -#include "raster/sprite.h" +#include "gui/jinete.h" #include "modules/editors.h" #include "modules/gui.h" +#include "raster/sprite.h" #include "recent_files.h" +#include "ui_context.h" #include "widgets/statebar.h" ////////////////////////////////////////////////////////////////////// @@ -57,7 +57,6 @@ struct OpenFileData Monitor *monitor; FileOp *fop; Progress *progress; - JThread thread; Frame* alert_window; }; @@ -66,10 +65,8 @@ struct OpenFileData * * [loading thread] */ -static void openfile_bg(void *fop_data) +static void openfile_bg(FileOp* fop) { - FileOp* fop = (FileOp*)fop_data; - try { fop_operate(fop); } @@ -160,55 +157,48 @@ void OpenFileCommand::onExecute(Context* context) unrecent = true; } else { - JThread thread = jthread_new(openfile_bg, fop); - if (thread) { - OpenFileData* data = new OpenFileData; + base::thread thread(&openfile_bg, fop); + OpenFileData* data = new OpenFileData; - data->fop = fop; - data->progress = app_get_statusbar()->addProgress(); - data->thread = thread; - data->alert_window = jalert_new(PACKAGE - "<fop = fop; + data->progress = app_get_statusbar()->addProgress(); + data->alert_window = jalert_new(PACKAGE + "<monitor = add_gui_monitor(monitor_openfile_bg, - monitor_free, data); + // Add a monitor to check the loading (FileOp) progress + data->monitor = add_gui_monitor(monitor_openfile_bg, + monitor_free, data); - data->alert_window->open_window_fg(); + data->alert_window->open_window_fg(); - if (data->monitor != NULL) - remove_gui_monitor(data->monitor); + if (data->monitor != NULL) + remove_gui_monitor(data->monitor); - // Stop the file-operation and wait the thread to exit - fop_stop(data->fop); - jthread_join(data->thread); + // Stop the file-operation and wait the thread to exit + fop_stop(data->fop); + thread.join(); - // Show any error - if (fop->error) - console.printf(fop->error); + // Show any error + if (fop->error) + console.printf(fop->error); - Sprite *sprite = fop->sprite; - if (sprite) { - UIContext* context = UIContext::instance(); + Sprite *sprite = fop->sprite; + if (sprite) { + UIContext* context = UIContext::instance(); - App::instance()->getRecentFiles()->addRecentFile(fop->filename); - context->add_sprite(sprite); + App::instance()->getRecentFiles()->addRecentFile(fop->filename); + context->add_sprite(sprite); - set_sprite_in_more_reliable_editor(sprite); - } - else if (!fop_is_stop(fop)) - unrecent = true; - - delete data->progress; - jwidget_free(data->alert_window); - fop_free(fop); - delete data; - } - else { - console.printf("Error creating thread to load the sprite"); - fop_free(fop); + set_sprite_in_more_reliable_editor(sprite); } + else if (!fop_is_stop(fop)) + unrecent = true; + + delete data->progress; + jwidget_free(data->alert_window); + fop_free(fop); + delete data; } // The file was not found or was loaded loaded with errors, diff --git a/src/commands/cmd_save_file.cpp b/src/commands/cmd_save_file.cpp index 722219521..36f37fc93 100644 --- a/src/commands/cmd_save_file.cpp +++ b/src/commands/cmd_save_file.cpp @@ -20,25 +20,24 @@ #include -#include "gui/jinete.h" - -#include "commands/command.h" #include "app.h" +#include "base/thread.h" +#include "commands/command.h" #include "console.h" #include "dialogs/filesel.h" #include "file/file.h" +#include "gui/jinete.h" #include "modules/gui.h" -#include "recent_files.h" #include "raster/sprite.h" -#include "widgets/statebar.h" +#include "recent_files.h" #include "sprite_wrappers.h" +#include "widgets/statebar.h" typedef struct SaveFileData { Monitor *monitor; FileOp *fop; Progress *progress; - JThread thread; Frame* alert_window; } SaveFileData; @@ -95,54 +94,52 @@ static void monitor_free(void *_data) static void save_sprite_in_background(Sprite* sprite, bool mark_as_saved) { FileOp *fop = fop_to_save_sprite(sprite); - if (fop) { - JThread thread = jthread_new(savefile_bg, fop); - if (thread) { - SaveFileData* data = new SaveFileData; + if (!fop) + return; - data->fop = fop; - data->progress = app_get_statusbar()->addProgress(); - data->thread = thread; - data->alert_window = jalert_new(PACKAGE - "<getFilename())); + base::thread thread(&savefile_bg, fop); + SaveFileData* data = new SaveFileData; - /* add a monitor to check the saving (FileOp) progress */ - data->monitor = add_gui_monitor(monitor_savefile_bg, - monitor_free, data); + data->fop = fop; + data->progress = app_get_statusbar()->addProgress(); + data->alert_window = jalert_new(PACKAGE + "<getFilename())); - /* TODO error handling */ + /* add a monitor to check the saving (FileOp) progress */ + data->monitor = add_gui_monitor(monitor_savefile_bg, + monitor_free, data); - data->alert_window->open_window_fg(); + /* TODO error handling */ - if (data->monitor != NULL) - remove_gui_monitor(data->monitor); + data->alert_window->open_window_fg(); - /* wait the `savefile_bg' thread */ - jthread_join(data->thread); + if (data->monitor != NULL) + remove_gui_monitor(data->monitor); - /* show any error */ - if (fop->error) { - Console console; - console.printf(fop->error); - } - /* no error? */ - else { - App::instance()->getRecentFiles()->addRecentFile(sprite->getFilename()); - if (mark_as_saved) - sprite->markAsSaved(); + /* wait the `savefile_bg' thread */ + thread.join(); - app_get_statusbar() - ->setStatusText(2000, "File %s, saved.", - get_filename(sprite->getFilename())); - } - - delete data->progress; - jwidget_free(data->alert_window); - fop_free(fop); - delete data; - } + /* show any error */ + if (fop->error) { + Console console; + console.printf(fop->error); } + /* no error? */ + else { + App::instance()->getRecentFiles()->addRecentFile(sprite->getFilename()); + if (mark_as_saved) + sprite->markAsSaved(); + + app_get_statusbar() + ->setStatusText(2000, "File %s, saved.", + get_filename(sprite->getFilename())); + } + + delete data->progress; + jwidget_free(data->alert_window); + fop_free(fop); + delete data; } /*********************************************************************/ diff --git a/src/commands/fx/effectbg.cpp b/src/commands/fx/effectbg.cpp index 4a90f648f..b8d1474f9 100644 --- a/src/commands/fx/effectbg.cpp +++ b/src/commands/fx/effectbg.cpp @@ -21,13 +21,13 @@ #include #include -#include "gui/jinete.h" - #include "app.h" #include "base/mutex.h" #include "base/scoped_lock.h" +#include "base/thread.h" #include "core/cfg.h" #include "effect/effect.h" +#include "gui/jinete.h" #include "modules/editors.h" #include "modules/gui.h" #include "raster/sprite.h" @@ -48,9 +48,8 @@ struct ThreadData float pos; /* current progress position */ bool done : 1; /* was the effect completelly applied? */ bool cancelled : 1; /* was the effect cancelled by the user? */ - Monitor *monitor; /* monitor to update the progress-bar */ - Progress *progress; /* the progress-bar */ - JThread thread; /* thread to apply the effect in background */ + Monitor* monitor; /* monitor to update the progress-bar */ + Progress* progress; /* the progress-bar */ Frame* alert_window; /* alert for the user to cancel the effect-progress if he wants */ }; @@ -91,10 +90,8 @@ static bool effect_is_cancelled_hook(void *_data) * * [effect thread] */ -static void effect_bg(void *_data) +static void effect_bg(ThreadData* data) { - ThreadData *data = (ThreadData *)_data; - /* apply the effect */ effect_apply_to_target(data->effect); @@ -160,14 +157,15 @@ void effect_apply_to_target_with_progressbar(Effect* effect) data->done = false; data->cancelled = false; data->progress = app_get_statusbar()->addProgress(); - data->thread = jthread_new(effect_bg, data); data->alert_window = jalert_new(PACKAGE "<monitor = add_gui_monitor(monitor_effect_bg, monitor_free, data); - /* TODO error handling */ + // Launch the thread to apply the effect in background + base::thread thread(&effect_bg, data); + // Open the alert window in foreground (this is modal, locks the main thread) data->alert_window->open_window_fg(); { @@ -178,8 +176,8 @@ void effect_apply_to_target_with_progressbar(Effect* effect) } } - /* wait the `effect_bg' thread */ - jthread_join(data->thread); + // Wait the `effect_bg' thread + thread.join(); delete data->progress; jwidget_free(data->alert_window); diff --git a/src/errno_unittest.cpp b/src/errno_unittest.cpp index 6ef0cef1f..84497e852 100644 --- a/src/errno_unittest.cpp +++ b/src/errno_unittest.cpp @@ -19,11 +19,9 @@ #include "tests/test.h" #include -#include "gui/jthread.h" +#include "base/thread.h" -static JThread thread; - -static void run_thread(void *data) +static void run_thread() { errno = 0; EXPECT_EQ(0, errno); @@ -36,8 +34,8 @@ TEST(Errno, ThreadSafe) // Run another thread that will be modify the errno variable, and // wait it (join). - thread = jthread_new(run_thread, NULL); - jthread_join(thread); + base::thread thr(&run_thread); + thr.join(); // See if errno was not modified in this thread. EXPECT_EQ(33, errno); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 57fe5c97c..ac0555743 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -39,7 +39,6 @@ add_library(gui-lib jsystem.cpp jtextbox.cpp jtheme.cpp - jthread.cpp jtooltips.cpp jview.cpp label.cpp diff --git a/src/gui/jinete.h b/src/gui/jinete.h index 79d613d47..a46ce7d05 100644 --- a/src/gui/jinete.h +++ b/src/gui/jinete.h @@ -39,7 +39,6 @@ #include "gui/jsystem.h" #include "gui/jtextbox.h" #include "gui/jtheme.h" -#include "gui/jthread.h" #include "gui/jtooltips.h" #include "gui/jview.h" #include "gui/widget.h" diff --git a/src/gui/jthread.cpp b/src/gui/jthread.cpp deleted file mode 100644 index 9998f17bb..000000000 --- a/src/gui/jthread.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// ASE gui library -// Copyright (C) 2001-2010 David Capello -// -// This source file is ditributed under a BSD-like license, please -// read LICENSE.txt for more information. - -#include "config.h" - -#include - -#include "gui/jthread.h" - -#if defined ALLEGRO_WINDOWS - #include - #include -#elif defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX - #include -#endif - -struct pthread_proxy_data { - void (*proc)(void*); - void* data; -}; - -#if defined ALLEGRO_WINDOWS -static DWORD WINAPI pthread_proxy(void* arg) -{ - pthread_proxy_data* ptr = reinterpret_cast(arg); - void (*proc)(void*) = ptr->proc; - void* data = ptr->data; - jfree(ptr); - - (*proc)(data); - return 0; -} -#elif defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX -static void* pthread_proxy(void* arg) -{ - pthread_proxy_data* ptr = reinterpret_cast(arg); - void (*proc)(void*) = ptr->proc; - void* data = ptr->data; - jfree(ptr); - - (*proc)(data); - return NULL; -} -#endif - -JThread jthread_new(void (*proc)(void*), void* data) -{ - struct pthread_proxy_data *ptr = jnew(struct pthread_proxy_data, 1); - ptr->proc = proc; - ptr->data = data; - -#if defined ALLEGRO_WINDOWS - - DWORD id; - HANDLE thread = CreateThread(NULL, 0, pthread_proxy, ptr, - CREATE_SUSPENDED, &id); - if (thread) - ResumeThread(thread); - return thread; - -#elif defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX - - pthread_t thread = 0; - if (pthread_create(&thread, NULL, pthread_proxy, ptr)) - return NULL; - else - return (JThread)thread; - -#else - #error ASE does not support threads for your platform -#endif -} - -void jthread_join(JThread thread) -{ -#if defined ALLEGRO_WINDOWS - WaitForSingleObject(thread, INFINITE); -#elif defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX - pthread_join((pthread_t)thread, NULL); -#else - #error ASE does not support threads for your platform -#endif -} diff --git a/src/gui/jthread.h b/src/gui/jthread.h deleted file mode 100644 index f5a748ebd..000000000 --- a/src/gui/jthread.h +++ /dev/null @@ -1,15 +0,0 @@ -// ASE gui library -// Copyright (C) 2001-2010 David Capello -// -// This source file is ditributed under a BSD-like license, please -// read LICENSE.txt for more information. - -#ifndef GUI_JTHREAD_H_INCLUDED -#define GUI_JTHREAD_H_INCLUDED - -#include "gui/jbase.h" - -JThread jthread_new(void (*proc)(void *data), void *data); -void jthread_join(JThread thread); - -#endif diff --git a/src/job.cpp b/src/job.cpp index af1d8cd81..b502b5a8e 100644 --- a/src/job.cpp +++ b/src/job.cpp @@ -18,14 +18,13 @@ #include "config.h" -#include "gui/jalert.h" -#include "gui/jthread.h" -#include "gui/widget.h" -#include "gui/frame.h" - #include "app.h" #include "base/mutex.h" #include "base/scoped_lock.h" +#include "base/thread.h" +#include "gui/frame.h" +#include "gui/jalert.h" +#include "gui/widget.h" #include "job.h" #include "modules/gui.h" #include "widgets/statebar.h" @@ -63,8 +62,10 @@ Job::~Job() m_monitor = NULL; } - if (m_thread) - jthread_join(m_thread); + if (m_thread) { + m_thread->join(); + delete m_thread; + } if (m_progress) delete m_progress; @@ -78,7 +79,7 @@ Job::~Job() void Job::startJob() { - m_thread = jthread_new(&Job::thread_proc, (void*)this); + m_thread = new base::thread(&Job::thread_proc, this); m_alert_window->open_window_fg(); } @@ -133,9 +134,8 @@ void Job::done() * * [worker thread] */ -void Job::thread_proc(void* data) +void Job::thread_proc(Job* self) { - Job* self = (Job*)data; try { self->onJob(); } diff --git a/src/job.h b/src/job.h index 732ab531c..a32e5933a 100644 --- a/src/job.h +++ b/src/job.h @@ -19,7 +19,7 @@ #ifndef CORE_JOB_H_INCLUDED #define CORE_JOB_H_INCLUDED -#include "gui/jbase.h" +namespace base { class thread; } class Frame; class Mutex; @@ -63,11 +63,11 @@ protected: private: void done(); - static void thread_proc(void* data); + static void thread_proc(Job* self); static void monitor_proc(void* data); static void monitor_free(void* data); - JThread m_thread; + base::thread* m_thread; Monitor* m_monitor; Progress* m_progress; Mutex* m_mutex; diff --git a/src/widgets/fileview.cpp b/src/widgets/fileview.cpp index 518de2a05..af9314504 100644 --- a/src/widgets/fileview.cpp +++ b/src/widgets/fileview.cpp @@ -22,6 +22,7 @@ #include #include "app.h" +#include "base/thread.h" #include "commands/commands.h" #include "console.h" #include "dialogs/filesel.h" @@ -69,7 +70,7 @@ typedef struct ThumbnailData IFileItem* fileitem; JWidget fileview; Image* thumbnail; - JThread thread; + base::thread* thread; Palette* palette; } ThumbnailData; @@ -84,7 +85,7 @@ static void fileview_generate_preview_of_selected_item(JWidget widget); static bool fileview_generate_thumbnail(JWidget widget, IFileItem* fileitem); static void fileview_stop_threads(FileView* fileview); -static void openfile_bg(void *data); +static void openfile_bg(ThumbnailData* data); static void monitor_thumbnail_generation(void *data); static void monitor_free_thumbnail_generation(void *data); @@ -724,7 +725,7 @@ static bool fileview_generate_thumbnail(JWidget widget, IFileItem* fileitem) data->fileview = widget; data->thumbnail = NULL; - data->thread = jthread_new(openfile_bg, data); + data->thread = new base::thread(&openfile_bg, data); if (data->thread) { // add a monitor to check the loading (FileOp) progress data->monitor = add_gui_monitor(monitor_thumbnail_generation, @@ -766,10 +767,9 @@ static void fileview_stop_threads(FileView* fileview) * * [loading thread] */ -static void openfile_bg(void *_data) +static void openfile_bg(ThumbnailData* data) { - ThumbnailData *data = (ThumbnailData *)_data; - FileOp *fop = (FileOp *)data->fop; + FileOp *fop = (FileOp*)data->fop; Sprite *sprite; int thumb_w, thumb_h; Image *image; @@ -820,8 +820,8 @@ static void openfile_bg(void *_data) */ static void monitor_thumbnail_generation(void *_data) { - ThumbnailData *data = (ThumbnailData *)_data; - FileOp *fop = (FileOp *)data->fop; + ThumbnailData* data = (ThumbnailData*)_data; + FileOp* fop = data->fop; /* is done? ...ok, now the thumbnail is in the main thread only... */ if (fop_is_done(fop)) { @@ -859,11 +859,12 @@ static void monitor_thumbnail_generation(void *_data) */ static void monitor_free_thumbnail_generation(void *_data) { - ThumbnailData *data = (ThumbnailData *)_data; - FileOp *fop = (FileOp *)data->fop; + ThumbnailData *data = (ThumbnailData*)_data; + FileOp *fop = data->fop; fop_stop(fop); - jthread_join(data->thread); + data->thread->join(); + delete data->thread; // remove the monitor from the list MonitorList& monitors(fileview_data(data->fileview)->monitors);