From 882e6894ff3be1ad3f71598b1d88521e16039384 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sat, 7 Jun 2014 06:26:31 -0700 Subject: [PATCH] Use GCD on OS X rather than boost.asio for the thread pool --- libaegisub/Makefile | 5 ++- libaegisub/osx/dispatch.mm | 81 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 libaegisub/osx/dispatch.mm diff --git a/libaegisub/Makefile b/libaegisub/Makefile index 7f570ec59..fa428afce 100644 --- a/libaegisub/Makefile +++ b/libaegisub/Makefile @@ -24,7 +24,6 @@ SRC += \ common/charset_6937.cpp \ common/charset_conv.cpp \ common/color.cpp \ - common/dispatch.cpp \ common/file_mapping.cpp \ common/format.cpp \ common/fs.cpp \ @@ -57,7 +56,9 @@ SRC += \ unix/util.cpp ifeq (yes, $(BUILD_DARWIN)) -SRC += osx/util.mm +SRC += osx/util.mm osx/dispatch.mm +else +SRC += common/dispatch.cpp endif HEADER += \ diff --git a/libaegisub/osx/dispatch.mm b/libaegisub/osx/dispatch.mm new file mode 100644 index 000000000..6268169fe --- /dev/null +++ b/libaegisub/osx/dispatch.mm @@ -0,0 +1,81 @@ +// Copyright (c) 2014, Thomas Goyne +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// Aegisub Project http://www.aegisub.org/ + +#include "libaegisub/dispatch.h" + +#include + +namespace { +std::function invoke_main; + +struct GCDQueue : agi::dispatch::Queue { + dispatch_queue_t queue; + GCDQueue(dispatch_queue_t queue) : queue(queue) { } + void DoInvoke(agi::dispatch::Thunk) override final { } +}; + +struct OwningQueue final : GCDQueue { + using GCDQueue::GCDQueue; + ~OwningQueue() { dispatch_release(queue); } +}; +} + +namespace agi { namespace dispatch { +void Init(std::function invoke_main) { + ::invoke_main = std::move(invoke_main); +} + +void Queue::Async(Thunk thunk) { + dispatch_async(static_cast(this)->queue, ^{ + 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(this)->queue, ^{ + try { + thunk(); + } + catch (...) { + *e_ptr = std::current_exception(); + } + }); + if (e) std::rethrow_exception(e); +} + +Queue& Main() { + static GCDQueue q(dispatch_get_main_queue()); + return q; +} + +Queue& Background() { + static GCDQueue q(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT)); + return q; +} + +std::unique_ptr Create() { + return std::unique_ptr(new OwningQueue(dispatch_queue_create("Aegisub worker queue", + DISPATCH_QUEUE_SERIAL))); +} +} }