diff --git a/test/miscellaneous/async_task.cpp b/test/miscellaneous/async_task.cpp new file mode 100644 index 000000000..4873ec5af --- /dev/null +++ b/test/miscellaneous/async_task.cpp @@ -0,0 +1,129 @@ +#include +#include +#include + +#include "../fixtures/util.hpp" + +#include + +using namespace mbgl::util; + +namespace { + +class TestWorker { +public: + TestWorker(AsyncTask *async_) + : async(async_) {} + + void run() { + for (unsigned i = 0; i < 100000; ++i) { + async->send(); + } + } + + void runWithCallback(std::function cb) { + for (unsigned i = 0; i < 100000; ++i) { + async->send(); + } + + cb(); + } + +private: + AsyncTask *async; +}; + +} + +TEST(AsyncTask, RequestCoalescing) { + RunLoop loop; + + unsigned count = 0; + AsyncTask async([&count] { ++count; }); + async.unref(); + + async.send(); + async.send(); + async.send(); + async.send(); + async.send(); + + loop.runOnce(); + + EXPECT_EQ(count, 1); +} + +TEST(AsyncTask, DestroyShouldNotRunQueue) { + RunLoop loop; + + unsigned count = 0; + auto async = std::make_unique([&count] { ++count; }); + + async->send(); + async.reset(); + + EXPECT_EQ(count, 0); +} + +TEST(AsyncTask, RequestCoalescingMultithreaded) { + RunLoop loop; + + unsigned count = 0; + AsyncTask async([&count] { ++count; }); + async.unref(); + + std::vector>> threads; + ThreadContext context = {"Test", ThreadType::Map, ThreadPriority::Regular}; + + unsigned numThreads = 50; + for (unsigned i = 0; i < numThreads; ++i) { + std::unique_ptr> thread = + std::make_unique>(context, &async); + + thread->invoke(&TestWorker::run); + threads.push_back(std::move(thread)); + } + + // Join all the threads + threads.clear(); + + loop.runOnce(); + + EXPECT_EQ(count, 1); +} + +TEST(AsyncTask, ThreadSafety) { + RunLoop loop; + + unsigned count = 0; + AsyncTask async([&count] { ++count; }); + async.unref(); + + unsigned numThreads = 50; + + auto callback = [&] { + if (!--numThreads) { + loop.stop(); + } + }; + + std::vector>> threads; + std::vector> requests; + ThreadContext context = {"Test", ThreadType::Map, ThreadPriority::Regular}; + + for (unsigned i = 0; i < numThreads; ++i) { + std::unique_ptr> thread = + std::make_unique>(context, &async); + + requests.push_back( + thread->invokeWithCallback(&TestWorker::runWithCallback, callback)); + + threads.push_back(std::move(thread)); + } + + loop.run(); + + // We expect here more than 1 but 1 would also be + // a valid result, although very unlikely (I hope). + EXPECT_GT(count, 1); +} diff --git a/test/test.gypi b/test/test.gypi index c96b4f686..74996a2e1 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -45,6 +45,7 @@ 'api/set_style.cpp', + 'miscellaneous/async_task.cpp', 'miscellaneous/clip_ids.cpp', 'miscellaneous/binpack.cpp', 'miscellaneous/bilinear.cpp',