[ios, osx] Replace libuv with native implementations

This commit is contained in:
John Firebaugh
2016-02-16 12:52:25 -08:00
parent 7e9a4f15c5
commit 879382f724
13 changed files with 215 additions and 28 deletions

View File

@@ -100,11 +100,11 @@ apackage: android-lib-mips
# Builds the Node.js library
.PHONY: node
node: ; $(RUN) HTTP=none ASSET=none Makefile/node
node: ; $(RUN) LOOP=uv HTTP=none ASSET=none Makefile/node
.PHONY: Xcode/node
Xcode/node: ; $(RUN) HTTP=none ASSET=none Xcode/node
Xcode/node: ; $(RUN) LOOP=uv HTTP=none ASSET=none Xcode/node
.PHONY: xnode
xnode: Xcode/node ; @open ./build/binding.xcodeproj

View File

@@ -15,33 +15,37 @@
'type': 'static_library',
'standalone_static_library': 1,
'sources': [
'../platform/default/async_task.cpp',
'../platform/default/run_loop.cpp',
'../platform/default/timer.cpp',
],
'include_dirs': [
'../include',
'../src',
],
'cflags_cc': [
'<@(libuv_cflags)',
],
'link_settings': {
'libraries': [
'<@(libuv_static_libs)',
'<@(libuv_ldflags)',
],
},
'conditions': [
['OS == "mac"', {
'xcode_settings': {
'OTHER_CPLUSPLUSFLAGS': [ '<@(libuv_cflags)' ],
}
['loop_lib == "darwin"', {
'sources': [
'../platform/darwin/src/async_task.cpp',
'../platform/darwin/src/run_loop.cpp',
'../platform/darwin/src/timer.cpp',
],
}],
['loop_lib == "uv"', {
'sources': [
'../platform/default/async_task.cpp',
'../platform/default/run_loop.cpp',
'../platform/default/timer.cpp',
],
'cflags_cc': [
'<@(libuv_cflags)',
],
'link_settings': {
'libraries': [
'<@(libuv_static_libs)',
'<@(libuv_ldflags)',
],
},
}]
],
},

View File

@@ -2,6 +2,7 @@ HEADLESS ?= none
PLATFORM ?= android
ASSET ?= zip
HTTP ?= android
LOOP ?= uv
GYP_FLAVOR_SUFFIX=-android

View File

@@ -0,0 +1,71 @@
#include <mbgl/util/async_task.hpp>
#include <CoreFoundation/CoreFoundation.h>
#include <atomic>
namespace mbgl {
namespace util {
class AsyncTask::Impl {
public:
Impl(std::function<void()>&& fn)
: task(std::move(fn)),
loop(CFRunLoopGetCurrent()) {
CFRunLoopSourceContext context = {
0,
this,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
perform
};
source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
}
~Impl() {
CFRunLoopRemoveSource(loop, source, kCFRunLoopDefaultMode);
CFRelease(source);
}
void maySend() {
if (!queued.test_and_set()) {
CFRunLoopSourceSignal(source);
CFRunLoopWakeUp(loop);
}
}
void runTask() {
queued.clear();
task();
}
private:
static void perform(void* info) {
reinterpret_cast<Impl*>(info)->runTask();
}
std::function<void()> task;
std::atomic_flag queued = ATOMIC_FLAG_INIT;
CFRunLoopRef loop;
CFRunLoopSourceRef source;
};
AsyncTask::AsyncTask(std::function<void()>&& fn)
: impl(std::make_unique<Impl>(std::move(fn))) {
}
AsyncTask::~AsyncTask() = default;
void AsyncTask::send() {
impl->maySend();
}
} // namespace util
} // namespace mbgl

View File

@@ -0,0 +1,51 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/thread_local.hpp>
#include <CoreFoundation/CoreFoundation.h>
namespace mbgl {
namespace util {
static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>;
static RunLoop mainRunLoop;
class RunLoop::Impl {
public:
std::unique_ptr<AsyncTask> async;
};
RunLoop* RunLoop::Get() {
assert(current.get());
return current.get();
}
RunLoop::RunLoop(Type)
: impl(std::make_unique<Impl>()) {
current.set(this);
impl->async = std::make_unique<AsyncTask>(std::bind(&RunLoop::process, this));
}
RunLoop::~RunLoop() {
current.set(nullptr);
}
void RunLoop::push(std::shared_ptr<WorkTask> task) {
withMutex([&] { queue.push(std::move(task)); });
impl->async->send();
}
void RunLoop::run() {
CFRunLoopRun();
}
void RunLoop::runOnce() {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
}
void RunLoop::stop() {
invoke([&] { CFRunLoopStop(CFRunLoopGetCurrent()); });
}
} // namespace util
} // namespace mbgl

View File

@@ -0,0 +1,60 @@
#include <mbgl/util/timer.hpp>
#include <CoreFoundation/CoreFoundation.h>
namespace mbgl {
namespace util {
CFTimeInterval toCFTimeInterval(Duration duration) {
return std::chrono::duration<CFTimeInterval>(duration).count();
}
CFAbsoluteTime toCFAbsoluteTime(Duration duration) {
return CFAbsoluteTimeGetCurrent() + toCFTimeInterval(duration);
}
class Timer::Impl {
public:
Impl(Duration timeout, Duration repeat, std::function<void()>&& fn)
: task(std::move(fn)),
loop(CFRunLoopGetCurrent()) {
CFRunLoopTimerContext context = {
0,
this,
nullptr,
nullptr,
nullptr
};
timer = CFRunLoopTimerCreate(kCFAllocatorDefault, toCFAbsoluteTime(timeout), toCFTimeInterval(repeat), 0, 0, perform, &context);
CFRunLoopAddTimer(loop, timer, kCFRunLoopDefaultMode);
}
~Impl() {
CFRunLoopRemoveTimer(loop, timer, kCFRunLoopDefaultMode);
CFRelease(timer);
}
private:
static void perform(CFRunLoopTimerRef, void* info) {
reinterpret_cast<Impl*>(info)->task();
}
std::function<void()> task;
CFRunLoopRef loop;
CFRunLoopTimerRef timer;
};
Timer::Timer() = default;
Timer::~Timer() = default;
void Timer::start(Duration timeout, Duration repeat, std::function<void()>&& cb) {
impl = std::make_unique<Impl>(timeout, repeat, std::move(cb));
}
void Timer::stop() {
impl.reset();
}
} // namespace util
} // namespace mbgl

View File

@@ -2,7 +2,6 @@
BOOST_VERSION=1.59.0
SQLITE_VERSION=system
LIBUV_VERSION=1.7.5
ZLIB_VERSION=system
GEOJSONVT_VERSION=4.1.0
VARIANT_VERSION=1.1.0

View File

@@ -2,6 +2,7 @@ HEADLESS = eagl
PLATFORM ?= ios
ASSET ?= fs
HTTP ?= nsurl
LOOP ?= darwin
HOST_VERSION = all

View File

@@ -6,7 +6,6 @@ set -u
NAME=Mapbox
OUTPUT=build/ios/pkg
LIBUV_VERSION=1.7.5
BUILDTYPE=${BUILDTYPE:-Release}
BUILD_FOR_DEVICE=${BUILD_DEVICE:-true}
@@ -150,7 +149,6 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then
step "Assembling static framework for iOS Simulator and devices…"
mkdir -p ${OUTPUT}/static/${NAME}.framework
libtool -static -no_warning_for_no_symbols \
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a` \
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojsonvt.a` \
-o ${OUTPUT}/static/${NAME}.framework/${NAME} \
${LIBS[@]/#/gyp/build/${BUILDTYPE}-iphoneos/libmbgl-} \
@@ -176,7 +174,6 @@ else
step "Assembling static library for iOS Simulator…"
mkdir -p ${OUTPUT}/static/${NAME}.framework
libtool -static -no_warning_for_no_symbols \
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a` \
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libgeojsonvt.a` \
-o ${OUTPUT}/static/${NAME}.framework/${NAME} \
${LIBS[@]/#/gyp/build/${BUILDTYPE}-iphonesimulator/libmbgl-}

View File

@@ -2,3 +2,4 @@ HEADLESS ?= glx
PLATFORM ?= linux
ASSET ?= fs
HTTP ?= curl
LOOP ?= uv

View File

@@ -2,3 +2,4 @@ HEADLESS ?= cgl
PLATFORM ?= osx
ASSET ?= fs
HTTP ?= nsurl
LOOP ?= darwin

View File

@@ -7,7 +7,6 @@ set -u
NAME=Mapbox
OUTPUT=build/osx/pkg
OSX_SDK_VERSION=`xcrun --sdk macosx --show-sdk-version`
LIBUV_VERSION=1.7.5
if [[ ${#} -eq 0 ]]; then # e.g. "make xpackage"
BUILDTYPE="Release"

View File

@@ -74,6 +74,7 @@ GYP_FLAGS += -Dhost=$(HOST)
GYP_FLAGS += -Iconfig/$(HOST_SLUG).gypi
GYP_FLAGS += -Dplatform_lib=$(PLATFORM)
GYP_FLAGS += -Dhttp_lib=$(HTTP)
GYP_FLAGS += -Dloop_lib=$(LOOP)
GYP_FLAGS += -Dasset_lib=$(ASSET)
GYP_FLAGS += -Dheadless_lib=$(HEADLESS)
GYP_FLAGS += -Dtest=$(BUILD_TEST)
@@ -184,6 +185,7 @@ print-env: $(SUBMODULES)
@printf "platform=$(COLOR_CYAN)%s$(FORMAT_END) " $(PLATFORM)
@printf "asset=$(COLOR_CYAN)%s$(FORMAT_END) " $(ASSET)
@printf "http=$(COLOR_CYAN)%s$(FORMAT_END) " $(HTTP)
@printf "loop=$(COLOR_CYAN)%s$(FORMAT_END) " $(LOOP)
@printf "\n"
# Never remove intermediate files