summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2016-08-03 19:24:04 +0300
committerThiago Marcos P. Santos <thiago@mapbox.com>2017-01-24 11:36:59 +0200
commitdd530dba0ea578f54347b08502ef6b7a9c0b813e (patch)
tree95e92f63ac79c9616370ccb522fc6b36ef53cc74
parent37b748e546e8ab0f1d922891bcdf00906be5ac24 (diff)
downloadqtlocation-mapboxgl-dd530dba0ea578f54347b08502ef6b7a9c0b813e.tar.gz
[core] Isolate pthread-based tls implementation
-rw-r--r--platform/android/config.cmake1
-rw-r--r--platform/default/thread_local.cpp58
-rw-r--r--platform/ios/config.cmake1
-rw-r--r--platform/linux/config.cmake1
-rw-r--r--platform/macos/config.cmake1
-rw-r--r--platform/qt/qt.cmake3
-rw-r--r--src/mbgl/util/thread_local.hpp40
-rw-r--r--test/util/thread_local.test.cpp26
8 files changed, 80 insertions, 51 deletions
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index c3c461ffa1..790e1f8bb5 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -79,6 +79,7 @@ macro(mbgl_platform_core)
PRIVATE platform/android/src/logging_android.cpp
PRIVATE platform/default/string_stdlib.cpp
PRIVATE platform/default/bidi.cpp
+ PRIVATE platform/default/thread_local.cpp
PRIVATE platform/default/utf.cpp
# Image handling
diff --git a/platform/default/thread_local.cpp b/platform/default/thread_local.cpp
new file mode 100644
index 0000000000..098ed90a3f
--- /dev/null
+++ b/platform/default/thread_local.cpp
@@ -0,0 +1,58 @@
+#include <mbgl/style/class_dictionary.hpp>
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/thread_local.hpp>
+
+#include <stdexcept>
+
+#include <pthread.h>
+
+namespace mbgl {
+namespace util {
+
+template class ThreadLocal<RunLoop>;
+template class ThreadLocal<int>;
+template class ThreadLocal<style::ClassDictionary>;
+
+template <class T>
+class ThreadLocal<T>::Impl {
+public:
+ pthread_key_t key;
+};
+
+template <class T>
+ThreadLocal<T>::ThreadLocal() : impl(std::make_unique<Impl>()) {
+ int ret = pthread_key_create(&impl->key, [](void *) {});
+
+ if (ret) {
+ throw std::runtime_error("Failed to init local storage key.");
+ }
+}
+
+template <class T>
+ThreadLocal<T>::~ThreadLocal() {
+ delete reinterpret_cast<T *>(get());
+
+ if (pthread_key_delete(impl->key)) {
+ throw std::runtime_error("Failed to delete local storage key.");
+ }
+}
+
+template <class T>
+T* ThreadLocal<T>::get() {
+ T* ret = reinterpret_cast<T*>(pthread_getspecific(impl->key));
+ if (!ret) {
+ return nullptr;
+ }
+
+ return ret;
+}
+
+template <class T>
+void ThreadLocal<T>::set(T* ptr) {
+ if (pthread_setspecific(impl->key, ptr)) {
+ throw std::runtime_error("Failed to set local storage.");
+ }
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake
index 1150171c54..6c8eb8e53b 100644
--- a/platform/ios/config.cmake
+++ b/platform/ios/config.cmake
@@ -41,6 +41,7 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/nsthread.mm
PRIVATE platform/darwin/src/string_nsstring.mm
PRIVATE platform/default/bidi.cpp
+ PRIVATE platform/default/thread_local.cpp
PRIVATE platform/default/utf.cpp
# Image handling
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index 13f3edb96f..bdd10c9b78 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -67,6 +67,7 @@ macro(mbgl_platform_core)
PRIVATE platform/default/string_stdlib.cpp
PRIVATE platform/default/thread.cpp
PRIVATE platform/default/bidi.cpp
+ PRIVATE platform/default/thread_local.cpp
PRIVATE platform/default/utf.cpp
# Image handling
diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake
index d7a9c894b8..f92c5ae933 100644
--- a/platform/macos/config.cmake
+++ b/platform/macos/config.cmake
@@ -37,6 +37,7 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/nsthread.mm
PRIVATE platform/darwin/src/string_nsstring.mm
PRIVATE platform/default/bidi.cpp
+ PRIVATE platform/default/thread_local.cpp
PRIVATE platform/default/utf.cpp
# Image handling
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 32ffe89bfe..b54bf88e8e 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -30,9 +30,10 @@ set(MBGL_QT_FILES
# Misc
PRIVATE platform/default/logging_stderr.cpp
- # Thread pool
+ # Thread
PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
+ PRIVATE platform/default/thread_local.cpp
# Platform integration
PRIVATE platform/qt/src/async_task.cpp
diff --git a/src/mbgl/util/thread_local.hpp b/src/mbgl/util/thread_local.hpp
index 67e3842ec6..b0e26356b4 100644
--- a/src/mbgl/util/thread_local.hpp
+++ b/src/mbgl/util/thread_local.hpp
@@ -2,9 +2,7 @@
#include <mbgl/util/noncopyable.hpp>
-#include <stdexcept>
-
-#include <pthread.h>
+#include <memory>
namespace mbgl {
namespace util {
@@ -17,39 +15,15 @@ public:
set(val);
}
- ThreadLocal() {
- int ret = pthread_key_create(&key, [](void *ptr) {
- delete reinterpret_cast<T *>(ptr);
- });
-
- if (ret) {
- throw std::runtime_error("Failed to init local storage key.");
- }
- }
-
- ~ThreadLocal() {
- if (pthread_key_delete(key)) {
- throw std::runtime_error("Failed to delete local storage key.");
- }
- }
+ ThreadLocal();
+ ~ThreadLocal();
- T* get() {
- T* ret = reinterpret_cast<T*>(pthread_getspecific(key));
- if (!ret) {
- return nullptr;
- }
-
- return ret;
- }
-
- void set(T* ptr) {
- if (pthread_setspecific(key, ptr)) {
- throw std::runtime_error("Failed to set local storage.");
- }
- }
+ T* get();
+ void set(T* ptr);
private:
- pthread_key_t key;
+ class Impl;
+ std::unique_ptr<Impl> impl;
};
} // namespace util
diff --git a/test/util/thread_local.test.cpp b/test/util/thread_local.test.cpp
index 4ee7042580..d67ea4b4b9 100644
--- a/test/util/thread_local.test.cpp
+++ b/test/util/thread_local.test.cpp
@@ -56,40 +56,32 @@ TEST(ThreadLocalStorage, NotSetReturnsNull) {
namespace {
-struct DtorCounter {
- ~DtorCounter() { ++(*value); }
- unsigned *value;
-};
-
class TestThreadReclaim {
public:
- TestThreadReclaim(DtorCounter* counter_) {
- counter.set(counter_);
+ TestThreadReclaim(int* data_) {
+ data.set(data_);
}
private:
- static ThreadLocal<DtorCounter> counter;
+ ThreadLocal<int> data;
};
-ThreadLocal<DtorCounter> TestThreadReclaim::counter;
-
} // namespace
TEST(ThreadLocalStorage, AutoReclaim) {
RunLoop loop;
- unsigned counter = 0;
-
- auto dtorCounter1 = new DtorCounter{ &counter };
- auto dtorCounter2 = new DtorCounter{ &counter };
+ auto data1 = new int;
+ auto data2 = new int;
ThreadContext context = {"Test"};
- auto thread1 = std::make_unique<Thread<TestThreadReclaim>>(context, dtorCounter1);
- auto thread2 = std::make_unique<Thread<TestThreadReclaim>>(context, dtorCounter2);
+ auto thread1 = std::make_unique<Thread<TestThreadReclaim>>(context, data1);
+ auto thread2 = std::make_unique<Thread<TestThreadReclaim>>(context, data2);
thread1.reset();
thread2.reset();
- EXPECT_EQ(counter, 2u);
+ // Should not leak, valgrind will
+ // let us know.
}