summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2015-06-23 20:08:30 +0300
committerThiago Marcos P. Santos <thiago@mapbox.com>2015-06-25 16:26:21 +0300
commita8b6b67dfeb79a2e7904a2aec6354161c4eb1b16 (patch)
treeffe6ebd296b440287979f8df74b9f59da0ee998d
parent7bb86368d4730c889f9b1f7007a7bada580db8ea (diff)
downloadqtlocation-mapboxgl-a8b6b67dfeb79a2e7904a2aec6354161c4eb1b16.tar.gz
Introduce the ThreadContext
mbgl::Thread will keep a ThreadContext for each running instance in a thread_local so we don't need to lookup a man in the Environment every time we need some info about the current thread. This patch is moving the ::currentlyOn check used on Debug build from the Environment class to the ThreadContext.
-rw-r--r--platform/default/sqlite_cache.cpp2
-rw-r--r--src/mbgl/map/map.cpp2
-rw-r--r--src/mbgl/map/map_context.cpp22
-rw-r--r--src/mbgl/storage/default_file_source.cpp2
-rw-r--r--src/mbgl/style/style.cpp6
-rw-r--r--src/mbgl/util/thread.hpp26
-rw-r--r--src/mbgl/util/thread_context.cpp34
-rw-r--r--src/mbgl/util/thread_context.hpp55
-rw-r--r--src/mbgl/util/uv_detail.hpp4
-rw-r--r--src/mbgl/util/worker.cpp3
-rw-r--r--test/miscellaneous/map_context.cpp2
-rw-r--r--test/miscellaneous/thread.cpp2
-rw-r--r--test/style/mock_file_source.cpp2
-rw-r--r--test/style/resource_loading.cpp2
14 files changed, 128 insertions, 36 deletions
diff --git a/platform/default/sqlite_cache.cpp b/platform/default/sqlite_cache.cpp
index 06d168ce4e..a2d2c6815d 100644
--- a/platform/default/sqlite_cache.cpp
+++ b/platform/default/sqlite_cache.cpp
@@ -62,7 +62,7 @@ std::string unifyMapboxURLs(const std::string &url) {
using namespace mapbox::sqlite;
SQLiteCache::SQLiteCache(const std::string& path_)
- : thread(std::make_unique<util::Thread<Impl>>("SQLite Cache", util::ThreadPriority::Low, path_)) {
+ : thread(std::make_unique<util::Thread<Impl>>(util::ThreadContext{"SQLite Cache", util::ThreadType::Unknown, util::ThreadPriority::Low}, path_)) {
}
SQLiteCache::~SQLiteCache() = default;
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 17bcd29893..c25d307c6e 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -12,7 +12,7 @@ namespace mbgl {
Map::Map(View& view, FileSource& fileSource, MapMode mode)
: data(std::make_unique<MapData>(view, mode)),
- context(std::make_unique<util::Thread<MapContext>>("Map", util::ThreadPriority::Regular, view, fileSource, *data))
+ context(std::make_unique<util::Thread<MapContext>>(util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, *data))
{
view.initialize(this);
}
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp
index 69d3c7e215..ecb9d84639 100644
--- a/src/mbgl/map/map_context.cpp
+++ b/src/mbgl/map/map_context.cpp
@@ -33,7 +33,7 @@ MapContext::MapContext(uv_loop_t* loop, View& view_, FileSource& fileSource, Map
updated(static_cast<UpdateType>(Update::Nothing)),
asyncUpdate(std::make_unique<uv::async>(loop, [this] { update(); })),
texturePool(std::make_unique<TexturePool>()) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
asyncUpdate->unref();
@@ -108,7 +108,7 @@ void MapContext::setStyleJSON(const std::string& json, const std::string& base)
}
void MapContext::loadStyleJSON(const std::string& json, const std::string& base) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
style.reset();
style = std::make_unique<Style>(json, base, asyncUpdate->get()->loop, env);
@@ -125,13 +125,13 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base)
}
void MapContext::updateTiles() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
style->update(data, transformState, *texturePool);
}
void MapContext::updateAnnotationTiles(const std::unordered_set<TileID, TileID::Hash>& ids) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
data.annotationManager.markStaleTiles(ids);
@@ -232,7 +232,7 @@ void MapContext::recalculateStyle(TimePoint now) {
}
void MapContext::update() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
const auto now = Clock::now();
data.setAnimationTime(now);
@@ -303,7 +303,7 @@ void MapContext::renderStill(StillImageCallback fn) {
}
void MapContext::render() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
// Cleanup OpenGL objects that we abandoned since the last render call.
env.performCleanup();
@@ -335,13 +335,13 @@ void MapContext::render() {
}
double MapContext::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
const SpritePosition pos = style->sprite->getSpritePosition(symbol);
return -pos.height / pos.pixelRatio / 2;
}
void MapContext::setSourceTileCacheSize(size_t size) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (size != sourceCacheSize) {
sourceCacheSize = size;
if (!style) return;
@@ -353,7 +353,7 @@ void MapContext::setSourceTileCacheSize(size_t size) {
}
void MapContext::onLowMemory() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (!style) return;
for (const auto &source : style->sources) {
source->onLowMemory();
@@ -362,12 +362,12 @@ void MapContext::onLowMemory() {
}
void MapContext::onTileDataChanged() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
triggerUpdate();
}
void MapContext::onResourceLoadingFailed(std::exception_ptr error) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (data.mode == MapMode::Still && callback) {
callback(error, nullptr);
diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp
index b46696aaa3..dcd0090da1 100644
--- a/src/mbgl/storage/default_file_source.cpp
+++ b/src/mbgl/storage/default_file_source.cpp
@@ -28,7 +28,7 @@ namespace algo = boost::algorithm;
namespace mbgl {
DefaultFileSource::DefaultFileSource(FileCache* cache, const std::string& root)
- : thread(std::make_unique<util::Thread<Impl>>("FileSource", util::ThreadPriority::Low, cache, root)) {
+ : thread(std::make_unique<util::Thread<Impl>>(util::ThreadContext{"FileSource", util::ThreadType::Unknown, util::ThreadPriority::Low}, cache, root)) {
}
DefaultFileSource::~DefaultFileSource() {
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 0713bda0a2..24771e1859 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -159,7 +159,7 @@ bool Style::isLoaded() const {
}
void Style::setObserver(Observer* observer_) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
assert(!observer);
observer = observer_;
@@ -206,7 +206,7 @@ void Style::onSpriteLoadingFailed(std::exception_ptr error) {
}
void Style::emitTileDataChanged() {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (observer) {
observer->onTileDataChanged();
@@ -214,7 +214,7 @@ void Style::emitTileDataChanged() {
}
void Style::emitResourceLoadingFailed(std::exception_ptr error) {
- assert(Environment::currentlyOn(ThreadType::Map));
+ assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
try {
if (error) {
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index f3a9baa6f3..5bd856cbbc 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -8,6 +8,7 @@
#include <functional>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/thread_context.hpp>
#include <mbgl/platform/platform.hpp>
namespace mbgl {
@@ -21,16 +22,11 @@ namespace util {
// Thread<> constructor blocks until the thread and the Object are fully created, so after the
// object creation, it's safe to obtain the Object stored in this thread.
-enum class ThreadPriority : bool {
- Regular,
- Low,
-};
-
template <class Object>
class Thread {
public:
template <class... Args>
- Thread(const std::string& name, ThreadPriority priority, Args&&... args);
+ Thread(const ThreadContext&, Args&&... args);
~Thread();
// Invoke object->fn(args...) in the runloop thread.
@@ -81,7 +77,7 @@ private:
}
template <typename P, std::size_t... I>
- void run(P&& params, std::index_sequence<I...>);
+ void run(ThreadContext, P&& params, std::index_sequence<I...>);
std::promise<void> running;
std::promise<void> joinable;
@@ -94,23 +90,21 @@ private:
template <class Object>
template <class... Args>
-Thread<Object>::Thread(const std::string& name, ThreadPriority priority, Args&&... args) {
+Thread<Object>::Thread(const ThreadContext& context, Args&&... args) {
// Note: We're using std::tuple<> to store the arguments because GCC 4.9 has a bug
// when expanding parameters packs captured in lambdas.
std::tuple<Args...> params = std::forward_as_tuple(::std::forward<Args>(args)...);
thread = std::thread([&] {
#ifdef __APPLE__
- pthread_setname_np(name.c_str());
- #else
- (void(name));
+ pthread_setname_np(context.name.c_str());
#endif
- if (priority == ThreadPriority::Low) {
+ if (context.priority == ThreadPriority::Low) {
platform::makeThreadLowPriority();
}
- run(std::move(params), std::index_sequence_for<Args...>{});
+ run(context, std::move(params), std::index_sequence_for<Args...>{});
});
running.get_future().get();
@@ -118,10 +112,12 @@ Thread<Object>::Thread(const std::string& name, ThreadPriority priority, Args&&.
template <class Object>
template <typename P, std::size_t... I>
-void Thread<Object>::run(P&& params, std::index_sequence<I...>) {
+void Thread<Object>::run(ThreadContext context, P&& params, std::index_sequence<I...>) {
uv::loop l;
{
+ ThreadContext::current.set(&context);
+
RunLoop loop_(l.get());
loop = &loop_;
@@ -133,6 +129,8 @@ void Thread<Object>::run(P&& params, std::index_sequence<I...>) {
loop = nullptr;
object = nullptr;
+
+ ThreadContext::current.set(nullptr);
}
// Run the loop again to ensure that async close callbacks have been called.
diff --git a/src/mbgl/util/thread_context.cpp b/src/mbgl/util/thread_context.cpp
new file mode 100644
index 0000000000..6742d5e75e
--- /dev/null
+++ b/src/mbgl/util/thread_context.cpp
@@ -0,0 +1,34 @@
+#include <mbgl/util/thread_context.hpp>
+
+namespace mbgl {
+namespace util {
+
+class MainThreadContextRegistrar {
+public:
+ MainThreadContextRegistrar() : context("Main", ThreadType::Main, ThreadPriority::Regular) {
+ ThreadContext::current.set(&context);
+ }
+
+ ~MainThreadContextRegistrar() {
+ ThreadContext::current.set(nullptr);
+ }
+
+private:
+ ThreadContext context;
+};
+
+ThreadContext::ThreadContext(const std::string& name_, ThreadType type_, ThreadPriority priority_)
+ : name(name_),
+ type(type_),
+ priority(priority_) {
+}
+
+uv::tls<ThreadContext> ThreadContext::current;
+
+// Will auto register the main thread context
+// at startup. Must be instantiated after the
+// ThreadContext::current object.
+MainThreadContextRegistrar registrar;
+
+}
+}
diff --git a/src/mbgl/util/thread_context.hpp b/src/mbgl/util/thread_context.hpp
new file mode 100644
index 0000000000..d4b56cafa8
--- /dev/null
+++ b/src/mbgl/util/thread_context.hpp
@@ -0,0 +1,55 @@
+#ifndef MBGL_UTIL_THREAD_CONTEXT
+#define MBGL_UTIL_THREAD_CONTEXT
+
+#include <mbgl/util/uv_detail.hpp>
+
+#include <cstdint>
+#include <string>
+#include <thread>
+
+namespace mbgl {
+namespace util {
+
+enum class ThreadPriority : bool {
+ Regular,
+ Low,
+};
+
+enum class ThreadType : uint8_t {
+ Main,
+ Map,
+ Worker,
+ Unknown,
+};
+
+struct ThreadContext {
+public:
+ ThreadContext(const std::string& name, ThreadType type, ThreadPriority priority);
+
+ static bool currentlyOn(ThreadType type) {
+ return current.get()->type == type;
+ }
+
+ static std::string getName() {
+ return current.get()->name;
+ }
+
+ static ThreadPriority getPriority() {
+ return current.get()->priority;
+ }
+
+private:
+ std::string name;
+ ThreadType type;
+ ThreadPriority priority;
+
+ static uv::tls<ThreadContext> current;
+
+ friend class MainThreadContextRegistrar;
+ template <class Object> friend class Thread;
+};
+
+}
+}
+
+#endif
diff --git a/src/mbgl/util/uv_detail.hpp b/src/mbgl/util/uv_detail.hpp
index 7e2c16a2a3..fc72ab6401 100644
--- a/src/mbgl/util/uv_detail.hpp
+++ b/src/mbgl/util/uv_detail.hpp
@@ -191,6 +191,10 @@ private:
template <class T>
class tls : public mbgl::util::noncopyable {
public:
+ inline tls(T* val) {
+ tls();
+ set(val);
+ }
inline tls() {
if (uv_key_create(&key) != 0) {
throw std::runtime_error("failed to initialize thread local storage key");
diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp
index 3022d30277..1806ba78ce 100644
--- a/src/mbgl/util/worker.cpp
+++ b/src/mbgl/util/worker.cpp
@@ -18,8 +18,9 @@ public:
};
Worker::Worker(std::size_t count) {
+ util::ThreadContext context = {"Worker", util::ThreadType::Worker, util::ThreadPriority::Low};
for (std::size_t i = 0; i < count; i++) {
- threads.emplace_back(std::make_unique<util::Thread<Impl>>("Worker", util::ThreadPriority::Low));
+ threads.emplace_back(std::make_unique<util::Thread<Impl>>(context));
}
}
diff --git a/test/miscellaneous/map_context.cpp b/test/miscellaneous/map_context.cpp
index 15061b1225..6e9ed85c3f 100644
--- a/test/miscellaneous/map_context.cpp
+++ b/test/miscellaneous/map_context.cpp
@@ -15,7 +15,7 @@ TEST(MapContext, DoubleStyleLoad) {
DefaultFileSource fileSource(nullptr);
MapData data(view, MapMode::Continuous);
- util::Thread<MapContext> context("Map", util::ThreadPriority::Regular, view, fileSource, data);
+ util::Thread<MapContext> context({"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, data);
context.invokeSync(&MapContext::setStyleJSON, "", "");
context.invokeSync(&MapContext::setStyleJSON, "", "");
diff --git a/test/miscellaneous/thread.cpp b/test/miscellaneous/thread.cpp
index b0dd2210e9..9767bc4b79 100644
--- a/test/miscellaneous/thread.cpp
+++ b/test/miscellaneous/thread.cpp
@@ -64,7 +64,7 @@ TEST(Thread, invoke) {
loop.invoke([&] {
EXPECT_EQ(tid, std::this_thread::get_id());
- Thread<TestObject> thread("Test", ThreadPriority::Regular, tid);
+ Thread<TestObject> thread({"Test", ThreadType::Map, ThreadPriority::Regular}, tid);
thread.invoke(&TestObject::fn1, 1);
thread.invokeWithResult<int>(&TestObject::fn2, [&] (int result) {
diff --git a/test/style/mock_file_source.cpp b/test/style/mock_file_source.cpp
index 0f2d93f71f..6aa735d0ea 100644
--- a/test/style/mock_file_source.cpp
+++ b/test/style/mock_file_source.cpp
@@ -133,7 +133,7 @@ void MockFileSource::Impl::dispatchPendingRequests() {
}
MockFileSource::MockFileSource(Type type, const std::string& match)
- : thread_(std::make_unique<util::Thread<Impl>>("FileSource", util::ThreadPriority::Low, type, match)) {
+ : thread_(std::make_unique<util::Thread<Impl>>(util::ThreadContext{"FileSource", util::ThreadType::Unknown, util::ThreadPriority::Low}, type, match)) {
}
void MockFileSource::setOnRequestDelayedCallback(std::function<void(void)> callback) {
diff --git a/test/style/resource_loading.cpp b/test/style/resource_loading.cpp
index fb6ba744a9..158af25909 100644
--- a/test/style/resource_loading.cpp
+++ b/test/style/resource_loading.cpp
@@ -117,7 +117,7 @@ void runTestCase(MockFileSource::Type type,
std::unique_ptr<util::Thread<MockMapContext>> context(
std::make_unique<util::Thread<MockMapContext>>(
- "Map", util::ThreadPriority::Regular, view, fileSource, callback));
+ util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, callback));
uv_run(loop.get(), UV_RUN_DEFAULT);