[core] Add a callback for platform RunLoop integration

Platform integration callback for platforms that do not have full
run loop integration or don't want to block at the Mapbox GL Native
loop. It will be called from any thread and is up to the platform
to, after receiving the callback, call RunLoop::runOnce() from the
same thread as the Map object lives.
This commit is contained in:
Thiago Marcos P. Santos
2020-03-11 01:31:13 +02:00
parent 09ab9420a9
commit 410e583db6
2 changed files with 61 additions and 0 deletions

View File

@@ -48,6 +48,15 @@ public:
void runOnce();
void stop();
using PlatformCallback = std::function<void()>;
// Platform integration callback for platforms that do not have full
// run loop integration or don't want to block at the Mapbox GL Native
// loop. It will be called from any thread and is up to the platform
// to, after receiving the callback, call RunLoop::runOnce() from the
// same thread as the Map object lives.
void setPlatformCallback(PlatformCallback&& callback) { platformCallback = std::move(callback); }
// So far only needed by the libcurl backend.
void addWatch(int fd, Event, std::function<void(int, Event)>&& callback);
void removeWatch(int fd);
@@ -95,6 +104,7 @@ private:
defaultQueue.emplace(std::move(task));
}
wake();
platformCallback();
}
void process() {
@@ -117,6 +127,8 @@ private:
}
}
PlatformCallback platformCallback = [] {};
Queue defaultQueue;
Queue highPriorityQueue;
std::mutex mutex;

View File

@@ -3,6 +3,10 @@
#include <mbgl/test/util.hpp>
#include <atomic>
#include <condition_variable>
#include <thread>
using namespace mbgl::util;
TEST(RunLoop, Stop) {
@@ -64,3 +68,48 @@ TEST(RunLoop, Priorities) {
EXPECT_EQ((std::vector<int>{ 2, 4, 1, 3 }), order);
}
TEST(RunLoop, PlatformIntegration) {
std::atomic<int> count1(0);
// No need to be atomic, it will run
// on the main thread.
int count2(0);
std::thread::id mainThread = std::this_thread::get_id();
RunLoop loop;
std::mutex mutex;
std::condition_variable cv;
loop.setPlatformCallback([&] {
EXPECT_NE(mainThread, std::this_thread::get_id());
count1++;
cv.notify_one();
});
auto threadBody = [&]() {
for (unsigned i = 0; i < 100000; ++i) {
loop.invoke([&] {
EXPECT_EQ(mainThread, std::this_thread::get_id());
count2++;
});
}
};
std::thread thread1(threadBody);
std::thread thread2(threadBody);
while (count2 < 200000) {
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock);
loop.runOnce();
}
EXPECT_EQ(count1, 200000);
EXPECT_EQ(count2, 200000);
thread1.join();
thread2.join();
}