mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 15:32:38 +00:00
Move thread class to base lib (the new thread class has a C++0x-like api).
This commit is contained in:
parent
2a73d6ffb9
commit
b66371f95a
@ -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")
|
||||
|
||||
|
@ -8,4 +8,5 @@ add_library(base-lib
|
||||
mutex.cpp
|
||||
path.cpp
|
||||
split_string.cpp
|
||||
string.cpp)
|
||||
string.cpp
|
||||
thread.cpp)
|
||||
|
149
src/base/thread.cpp
Normal file
149
src/base/thread.cpp
Normal file
@ -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 <windows.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <pthread.h> // 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<func_wrapper*>(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
|
||||
}
|
141
src/base/thread.h
Normal file
141
src/base/thread.h
Normal file
@ -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<class Callable>
|
||||
thread(const Callable& f) {
|
||||
launch_thread(new func_wrapper0<Callable>(f));
|
||||
}
|
||||
|
||||
// Create a new thread with one argument
|
||||
template<class Callable, class A>
|
||||
thread(const Callable& f, A a) {
|
||||
launch_thread(new func_wrapper1<Callable, A>(f, a));
|
||||
}
|
||||
|
||||
// Create a new thread with two arguments
|
||||
template<class Callable, class A, class B>
|
||||
thread(const Callable& f, A a, B b) {
|
||||
launch_thread(new func_wrapper2<Callable, A, B>(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 Callable>
|
||||
class func_wrapper0 : public func_wrapper {
|
||||
public:
|
||||
Callable f;
|
||||
func_wrapper0(const Callable& f) : f(f) { }
|
||||
void operator()() { f(); }
|
||||
};
|
||||
|
||||
template<class Callable, class A>
|
||||
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 Callable, class A, class B>
|
||||
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
|
56
src/base/thread_unittest.cpp
Normal file
56
src/base/thread_unittest.cpp
Normal file
@ -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 <iostream>
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -18,22 +18,22 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <allegro.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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
|
||||
"<<Loading file:<<%s||&Cancel",
|
||||
get_filename(m_filename.c_str()));
|
||||
data->fop = fop;
|
||||
data->progress = app_get_statusbar()->addProgress();
|
||||
data->alert_window = jalert_new(PACKAGE
|
||||
"<<Loading file:<<%s||&Cancel",
|
||||
get_filename(m_filename.c_str()));
|
||||
|
||||
// Add a monitor to check the loading (FileOp) progress
|
||||
data->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,
|
||||
|
@ -20,25 +20,24 @@
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#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
|
||||
"<<Saving file:<<%s||&Cancel",
|
||||
get_filename(sprite->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
|
||||
"<<Saving file:<<%s||&Cancel",
|
||||
get_filename(sprite->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;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -21,13 +21,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
"<<Applying effect...||&Cancel");
|
||||
data->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);
|
||||
|
@ -19,11 +19,9 @@
|
||||
#include "tests/test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#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);
|
||||
|
@ -39,7 +39,6 @@ add_library(gui-lib
|
||||
jsystem.cpp
|
||||
jtextbox.cpp
|
||||
jtheme.cpp
|
||||
jthread.cpp
|
||||
jtooltips.cpp
|
||||
jview.cpp
|
||||
label.cpp
|
||||
|
@ -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"
|
||||
|
@ -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 <allegro.h>
|
||||
|
||||
#include "gui/jthread.h"
|
||||
|
||||
#if defined ALLEGRO_WINDOWS
|
||||
#include <winalleg.h>
|
||||
#include <process.h>
|
||||
#elif defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX
|
||||
#include <pthread.h>
|
||||
#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<pthread_proxy_data*>(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<pthread_proxy_data*>(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
|
||||
}
|
@ -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
|
20
src/job.cpp
20
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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <allegro.h>
|
||||
|
||||
#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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user