mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
debuged some horrible race conditions & deadlocks
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@160 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -144,6 +144,8 @@ void resample_and_clip(const Image& img_in, Image& img_out, wxRect rect) {
|
||||
// fill an image with 100% transparent, except for the given rectangle
|
||||
void fill_transparent(Image& img, int dx, int dy, int w, int h) {
|
||||
if (!img.HasAlpha()) img.InitAlpha();
|
||||
memset(img.GetAlpha(), 0, img.GetWidth() * img.GetHeight());
|
||||
/*/?
|
||||
int iw = img.GetWidth(), ih = img.GetHeight();
|
||||
Byte* data = img.GetAlpha();
|
||||
// fill
|
||||
@@ -160,6 +162,7 @@ void fill_transparent(Image& img, int dx, int dy, int w, int h) {
|
||||
for (; y < ih ; ++y) {
|
||||
for (int x = 0 ; x < iw ; ++x) *data++ = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void resample_preserve_aspect(const Image& img_in, Image& img_out) {
|
||||
|
||||
@@ -37,8 +37,10 @@ class DropDownHider : public wxEvtHandler {
|
||||
// don't just use ev.Skip(), because this event handler will be removed by hiding,
|
||||
// so there will be no next handler to skip to
|
||||
wxEvtHandler* nh = GetNextHandler();
|
||||
wxLogDebug(L"close to %p", nh);
|
||||
list.hide(false);
|
||||
if (nh) nh->ProcessEvent(ev);
|
||||
wxLogDebug(L"/close to %p", nh);
|
||||
return false;
|
||||
} else {
|
||||
// if (t !=10093 && t !=10098 && t !=10097 && t !=10099 && t !=10004 && t !=10062
|
||||
|
||||
@@ -58,7 +58,6 @@ wxThread::ExitCode ThumbnailThreadWorker::Entry() {
|
||||
while (true) {
|
||||
do {
|
||||
Sleep(1);
|
||||
if (TestDestroy()) return 0;
|
||||
} while (stop);
|
||||
// get a request
|
||||
{
|
||||
@@ -71,9 +70,7 @@ wxThread::ExitCode ThumbnailThreadWorker::Entry() {
|
||||
parent->open_requests.pop_front();
|
||||
}
|
||||
// perform request
|
||||
if (TestDestroy()) return 0;
|
||||
Image img = current->generate();
|
||||
if (TestDestroy()) return 0;
|
||||
// store in cache
|
||||
if (img.Ok()) {
|
||||
String filename = image_cache_dir() + safe_filename(current->cache_name) + _(".png");
|
||||
@@ -107,10 +104,6 @@ ThumbnailThread::ThumbnailThread()
|
||||
, worker(nullptr)
|
||||
{}
|
||||
|
||||
ThumbnailThread::~ThumbnailThread() {
|
||||
abortAll();
|
||||
}
|
||||
|
||||
void ThumbnailThread::request(const ThumbnailRequestP& request) {
|
||||
assert(wxThread::IsMain());
|
||||
// Is the request in progress?
|
||||
@@ -172,7 +165,7 @@ bool ThumbnailThread::done(void* owner) {
|
||||
void ThumbnailThread::abort(void* owner) {
|
||||
assert(wxThread::IsMain());
|
||||
mutex.Lock();
|
||||
if (worker && worker->current->owner == owner) {
|
||||
if (worker && worker->current && worker->current->owner == owner) {
|
||||
// a request for this owner is in progress, wait until it is done
|
||||
worker->stop = true;
|
||||
completed.Wait();
|
||||
@@ -183,8 +176,8 @@ void ThumbnailThread::abort(void* owner) {
|
||||
for (size_t i = 0 ; i < open_requests.size() ; ) {
|
||||
if (open_requests[i]->owner == owner) {
|
||||
// remove
|
||||
open_requests.erase(open_requests.begin() + i, open_requests.begin() + i + 1);
|
||||
request_names.erase(open_requests[i]);
|
||||
open_requests.erase(open_requests.begin() + i, open_requests.begin() + i + 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
@@ -193,8 +186,8 @@ void ThumbnailThread::abort(void* owner) {
|
||||
for (size_t i = 0 ; i < closed_requests.size() ; ) {
|
||||
if (closed_requests[i].first->owner == owner) {
|
||||
// remove
|
||||
closed_requests.erase(closed_requests.begin() + i, closed_requests.begin() + i + 1);
|
||||
request_names.erase(closed_requests[i].first);
|
||||
closed_requests.erase(closed_requests.begin() + i, closed_requests.begin() + i + 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
@@ -208,10 +201,14 @@ void ThumbnailThread::abortAll() {
|
||||
open_requests.clear();
|
||||
closed_requests.clear();
|
||||
request_names.clear();
|
||||
if (worker) {
|
||||
// a request is in progress, wait until it is done, killing the worker
|
||||
// end worker
|
||||
if (worker && worker->current) {
|
||||
completed.Wait();
|
||||
} else {
|
||||
mutex.Unlock();
|
||||
}
|
||||
// There may still be a worker, but if there is, it has no current object, so it is
|
||||
// in, before or after the stop loop. It can do nothing but end.
|
||||
// An unfortunate side effect is that we might leak some memory (of the worker object),
|
||||
// when the thread gets Kill()ed by wx.
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ class ThumbnailRequest {
|
||||
class ThumbnailThread {
|
||||
public:
|
||||
ThumbnailThread();
|
||||
~ThumbnailThread();
|
||||
|
||||
/// Request a thumbnail, it may be store()d immediatly if the thumbnail is cached
|
||||
void request(const ThumbnailRequestP& request);
|
||||
@@ -58,6 +57,7 @@ class ThumbnailThread {
|
||||
/// Abort all thumbnail requests for the given owner
|
||||
void abort(void* owner);
|
||||
/// Abort all computations
|
||||
/** *must* be called at application exit */
|
||||
void abortAll();
|
||||
|
||||
private:
|
||||
|
||||
@@ -66,7 +66,9 @@ DropDownChoiceList::DropDownChoiceList(Window* parent, bool is_submenu, ChoiceVa
|
||||
, group(group)
|
||||
, cve(cve)
|
||||
{
|
||||
icon_size.width = 16;
|
||||
icon_size.width = 16;
|
||||
icon_size.height = 16;
|
||||
item_size.height = max(16., item_size.height);
|
||||
}
|
||||
|
||||
size_t DropDownChoiceList::itemCount() const {
|
||||
@@ -183,7 +185,9 @@ void DropDownChoiceList::generateThumbnailImages() {
|
||||
|
||||
void DropDownChoiceList::onIdle(wxIdleEvent& ev) {
|
||||
if (!isRoot()) return;
|
||||
thumbnail_thread.done(&cve);
|
||||
if (thumbnail_thread.done(&cve)) {
|
||||
Refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(DropDownChoiceList, DropDownList)
|
||||
@@ -201,6 +205,8 @@ ChoiceValueEditor::~ChoiceValueEditor() {
|
||||
}
|
||||
|
||||
void ChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
//HACK TODO REMOVEME
|
||||
thumbnail_thread.abortAll();
|
||||
drop_down->onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
}
|
||||
void ChoiceValueEditor::onChar(wxKeyEvent& ev) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <gui/update_checker.hpp>
|
||||
#include <gui/set/window.hpp>
|
||||
#include <gui/symbol/window.hpp>
|
||||
#include <gui/thumbnail_thread.hpp>
|
||||
#include <wx/fs_inet.h>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Main function/class
|
||||
@@ -73,6 +74,7 @@ bool MSE::OnInit() {
|
||||
// ----------------------------------------------------------------------------- : Exit
|
||||
|
||||
int MSE::OnExit() {
|
||||
thumbnail_thread.abortAll();
|
||||
settings.write();
|
||||
packages.destroy();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user