Asynchronous GeometryTile deletion (#2051)
Co-authored-by: Tim Sylvester <tim@wetdogweather.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/actor/actor_ref.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/platform/settings.hpp>
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
@@ -134,6 +135,11 @@ TEST(Thread, Concurrency) {
|
||||
unsigned numMessages = 100000;
|
||||
std::atomic_uint completed(numMessages);
|
||||
|
||||
auto& settings = platform::Settings::getInstance();
|
||||
if (!settings.get(platform::EXPERIMENTAL_THREAD_PRIORITY_WORKER).getDouble()) {
|
||||
settings.set(platform::EXPERIMENTAL_THREAD_PRIORITY_WORKER, 0.5);
|
||||
}
|
||||
|
||||
Actor<TestWorker> poolWorker(Scheduler::GetBackground());
|
||||
auto poolWorkerRef = poolWorker.self();
|
||||
|
||||
@@ -328,3 +334,108 @@ TEST(Thread, DeleteBeforeChildStarts) {
|
||||
// Should process the queue before destruction.
|
||||
ASSERT_TRUE(flag);
|
||||
}
|
||||
|
||||
TEST(Thread, PoolWait) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
|
||||
constexpr int threadCount = 10;
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
pool->schedule([&] { std::this_thread::sleep_for(Milliseconds(100)); });
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
}
|
||||
|
||||
TEST(Thread, PoolWaitRecursiveAdd) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
|
||||
pool->schedule([&] {
|
||||
// Scheduled tasks can add more tasks
|
||||
pool->schedule([&] {
|
||||
std::this_thread::sleep_for(Milliseconds(10));
|
||||
pool->schedule([&] { std::this_thread::sleep_for(Milliseconds(10)); });
|
||||
});
|
||||
std::this_thread::sleep_for(Milliseconds(10));
|
||||
});
|
||||
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
}
|
||||
|
||||
TEST(Thread, PoolWaitAdd) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
auto seq = Scheduler::GetSequenced();
|
||||
|
||||
// add new tasks every few milliseconds
|
||||
std::atomic<bool> addActive{true};
|
||||
std::atomic<int> added{0};
|
||||
std::atomic<int> executed{0};
|
||||
seq->schedule([&] {
|
||||
while (addActive) {
|
||||
pool->schedule([&] { executed++; });
|
||||
added++;
|
||||
}
|
||||
});
|
||||
|
||||
// Wait be sure some are added
|
||||
while (added < 1) {
|
||||
std::this_thread::sleep_for(Milliseconds(10));
|
||||
}
|
||||
|
||||
// Add an item that should take long enough to be confident that
|
||||
// more items would be added by the sequential task if not blocked
|
||||
pool->schedule([&] { std::this_thread::sleep_for(Milliseconds(100)); });
|
||||
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
|
||||
addActive = false;
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
}
|
||||
|
||||
TEST(Thread, PoolWaitTimeout) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
|
||||
std::mutex mutex;
|
||||
{
|
||||
std::lock_guard<std::mutex> outerLock(mutex);
|
||||
pool->schedule([&] { std::lock_guard<std::mutex> innerLock(mutex); });
|
||||
|
||||
// should always time out
|
||||
EXPECT_EQ(1, pool->waitForEmpty(Milliseconds(100)));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
}
|
||||
|
||||
TEST(Thread, PoolWaitException) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
|
||||
std::atomic<int> caught{0};
|
||||
pool->setExceptionHandler([&](const auto) { caught++; });
|
||||
|
||||
constexpr int threadCount = 3;
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
pool->schedule([=] {
|
||||
std::this_thread::sleep_for(Milliseconds(i));
|
||||
if (i & 1) {
|
||||
throw std::runtime_error("test");
|
||||
} else {
|
||||
throw 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Exceptions shouldn't cause deadlocks by, e.g., abandoning locks.
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
EXPECT_EQ(threadCount, caught);
|
||||
}
|
||||
|
||||
#if defined(NDEBUG)
|
||||
TEST(Thread, WrongThread) {
|
||||
auto pool = Scheduler::GetBackground();
|
||||
|
||||
// Asserts in debug builds, silently ignored in release.
|
||||
pool->schedule([&] { EXPECT_EQ(0, pool->waitForEmpty()); });
|
||||
|
||||
EXPECT_EQ(0, pool->waitForEmpty());
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user