mirror of https://github.com/odrling/Aegisub
Use wx events for invoking on the main thread on OS X
Dispatching to the main queue with GCD does not work when there is a modal dialog active.
This commit is contained in:
parent
e675cf10da
commit
0cc941e559
|
@ -17,19 +17,71 @@
|
||||||
#include "libaegisub/dispatch.h"
|
#include "libaegisub/dispatch.h"
|
||||||
|
|
||||||
#include <dispatch/dispatch.h>
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::function<void (agi::dispatch::Thunk)> invoke_main;
|
using namespace agi::dispatch;
|
||||||
|
std::function<void (Thunk)> invoke_main;
|
||||||
|
|
||||||
struct GCDQueue : agi::dispatch::Queue {
|
struct OSXQueue : Queue {
|
||||||
dispatch_queue_t queue;
|
virtual void DoSync(Thunk thunk)=0;
|
||||||
GCDQueue(dispatch_queue_t queue) : queue(queue) { }
|
|
||||||
void DoInvoke(agi::dispatch::Thunk) override final { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OwningQueue final : GCDQueue {
|
struct MainQueue final : OSXQueue {
|
||||||
using GCDQueue::GCDQueue;
|
void DoInvoke(Thunk thunk) override { invoke_main(thunk); }
|
||||||
~OwningQueue() { dispatch_release(queue); }
|
|
||||||
|
void DoSync(Thunk thunk) {
|
||||||
|
std::mutex m;
|
||||||
|
std::condition_variable cv;
|
||||||
|
std::unique_lock<std::mutex> l(m);
|
||||||
|
std::exception_ptr e;
|
||||||
|
bool done = false;
|
||||||
|
invoke_main([&]{
|
||||||
|
std::unique_lock<std::mutex> l(m);
|
||||||
|
try {
|
||||||
|
thunk();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
e = std::current_exception();
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
cv.notify_all();
|
||||||
|
});
|
||||||
|
cv.wait(l, [&]{ return done; });
|
||||||
|
if (e) std::rethrow_exception(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCDQueue final : OSXQueue {
|
||||||
|
dispatch_queue_t queue;
|
||||||
|
GCDQueue(dispatch_queue_t queue) : queue(queue) { }
|
||||||
|
~GCDQueue() { dispatch_release(queue); }
|
||||||
|
|
||||||
|
void DoInvoke(Thunk thunk) override {
|
||||||
|
dispatch_async(queue, ^{
|
||||||
|
try {
|
||||||
|
thunk();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
auto e = std::current_exception();
|
||||||
|
invoke_main([=] { std::rethrow_exception(e); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSync(Thunk thunk) override {
|
||||||
|
std::exception_ptr e;
|
||||||
|
std::exception_ptr *e_ptr = &e;
|
||||||
|
dispatch_sync(queue, ^{
|
||||||
|
try {
|
||||||
|
thunk();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
*e_ptr = std::current_exception();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (e) std::rethrow_exception(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,34 +90,11 @@ void Init(std::function<void (Thunk)> invoke_main) {
|
||||||
::invoke_main = std::move(invoke_main);
|
::invoke_main = std::move(invoke_main);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Queue::Async(Thunk thunk) {
|
void Queue::Async(Thunk thunk) { DoInvoke(std::move(thunk)); }
|
||||||
dispatch_async(static_cast<GCDQueue *>(this)->queue, ^{
|
void Queue::Sync(Thunk thunk) { static_cast<OSXQueue *>(this)->DoSync(std::move(thunk)); }
|
||||||
try {
|
|
||||||
thunk();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
auto e = std::current_exception();
|
|
||||||
invoke_main([=] { std::rethrow_exception(e); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Queue::Sync(Thunk thunk) {
|
|
||||||
std::exception_ptr e;
|
|
||||||
std::exception_ptr *e_ptr = &e;
|
|
||||||
dispatch_sync(static_cast<GCDQueue *>(this)->queue, ^{
|
|
||||||
try {
|
|
||||||
thunk();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
*e_ptr = std::current_exception();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (e) std::rethrow_exception(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Queue& Main() {
|
Queue& Main() {
|
||||||
static GCDQueue q(dispatch_get_main_queue());
|
static MainQueue q;
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +104,7 @@ Queue& Background() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Queue> Create() {
|
std::unique_ptr<Queue> Create() {
|
||||||
return std::unique_ptr<Queue>(new OwningQueue(dispatch_queue_create("Aegisub worker queue",
|
return std::unique_ptr<Queue>(new GCDQueue(dispatch_queue_create("Aegisub worker queue",
|
||||||
DISPATCH_QUEUE_SERIAL)));
|
DISPATCH_QUEUE_SERIAL)));
|
||||||
}
|
}
|
||||||
} }
|
} }
|
||||||
|
|
Loading…
Reference in New Issue