summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-10-08 15:27:33 +0200
committerKonstantin Käfer <mail@kkaefer.com>2014-10-08 15:27:33 +0200
commit91f40daa6911f57f3dca534080241b46844c71b7 (patch)
tree30b7ae192785add4dbaa0ed4304faab6336079ef
parent36b7bb0c0991b3c5c3a7d001139b120bee854484 (diff)
downloadqtlocation-mapboxgl-91f40daa6911f57f3dca534080241b46844c71b7.tar.gz
don't do concurrent access to a static member variable
in situations where the renderer is used from multiple threads, this causes memory corruption. fixes mapbox/node-mapbox-gl-native#7
-rw-r--r--include/mbgl/style/class_dictionary.hpp13
-rw-r--r--src/style/class_dictionary.cpp34
-rw-r--r--src/style/style_layer.cpp2
-rw-r--r--src/style/style_parser.cpp2
4 files changed, 39 insertions, 12 deletions
diff --git a/include/mbgl/style/class_dictionary.hpp b/include/mbgl/style/class_dictionary.hpp
index c7f9c6a284..ecf80be3e3 100644
--- a/include/mbgl/style/class_dictionary.hpp
+++ b/include/mbgl/style/class_dictionary.hpp
@@ -14,17 +14,22 @@ enum class ClassID : uint32_t {
};
class ClassDictionary {
+private:
+ ClassDictionary();
+
public:
+ static ClassDictionary &Get();
+
// Returns an ID for a class name. If the class name does not yet have an ID, one is
// auto-generated and stored for future reference.
- static ClassID Lookup(const std::string &class_name);
+ ClassID lookup(const std::string &class_name);
// Returns either Fallback, Default or Named, depending on the type of the class id.
- static ClassID Normalize(ClassID id);
+ ClassID normalize(ClassID id);
private:
- static std::unordered_map<std::string, ClassID> store;
- static uint32_t offset;
+ std::unordered_map<std::string, ClassID> store = { { "", ClassID::Default } };
+ uint32_t offset = 0;
};
}
diff --git a/src/style/class_dictionary.cpp b/src/style/class_dictionary.cpp
index 6e1eb5a879..ba7c0d55be 100644
--- a/src/style/class_dictionary.cpp
+++ b/src/style/class_dictionary.cpp
@@ -1,8 +1,34 @@
#include <mbgl/style/class_dictionary.hpp>
+#include <uv.h>
+
namespace mbgl {
-ClassID ClassDictionary::Lookup(const std::string &class_name) {
+ClassDictionary::ClassDictionary() {}
+
+ClassDictionary &ClassDictionary::Get() {
+ // Note: We should eventually switch to uv_key_* functions, but libuv 0.10 doesn't have these
+ // yet. Instead, we're using the pthread functions directly for now.
+ static pthread_once_t store_once = PTHREAD_ONCE_INIT;
+ static pthread_key_t store_key;
+
+ // Create the key.
+ pthread_once(&store_once, []() {
+ pthread_key_create(&store_key, [](void *ptr) {
+ delete reinterpret_cast<ClassDictionary *>(ptr);
+ });
+ });
+
+ ClassDictionary *ptr = reinterpret_cast<ClassDictionary *>(pthread_getspecific(store_key));
+ if (ptr == nullptr) {
+ ptr = new ClassDictionary();
+ pthread_setspecific(store_key, ptr);
+ }
+
+ return *ptr;
+}
+
+ClassID ClassDictionary::lookup(const std::string &class_name) {
auto it = store.find(class_name);
if (it == store.end()) {
// Insert the class name into the store.
@@ -14,7 +40,7 @@ ClassID ClassDictionary::Lookup(const std::string &class_name) {
}
}
-ClassID ClassDictionary::Normalize(ClassID id) {
+ClassID ClassDictionary::normalize(ClassID id) {
if (id >= ClassID::Named) {
return ClassID::Named;
} else {
@@ -22,8 +48,4 @@ ClassID ClassDictionary::Normalize(ClassID id) {
}
}
-
-std::unordered_map<std::string, ClassID> ClassDictionary::store = { { "", ClassID::Default } };
-uint32_t ClassDictionary::offset = 0;
-
}
diff --git a/src/style/style_layer.cpp b/src/style/style_layer.cpp
index 4f758fe723..b1b878cc8d 100644
--- a/src/style/style_layer.cpp
+++ b/src/style/style_layer.cpp
@@ -23,7 +23,7 @@ void StyleLayer::setClasses(const std::vector<std::string> &class_names, const t
for (auto it = class_names.rbegin(); it != class_names.rend(); it++) {
const std::string &class_name = *it;
// From here on, we're only dealing with IDs to avoid comparing strings all the time.
- const ClassID class_id = ClassDictionary::Lookup(class_name);
+ const ClassID class_id = ClassDictionary::Get().lookup(class_name);
applyClassProperties(class_id, already_applied, now, defaultTransition);
}
diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp
index 7e695e71cb..ad7694d9a9 100644
--- a/src/style/style_parser.cpp
+++ b/src/style/style_parser.cpp
@@ -554,7 +554,7 @@ void StyleParser::parseStyles(JSVal value, std::map<ClassID, ClassProperties> &s
if (name == "style") {
parseStyle(replaceConstant(itr->value), styles[ClassID::Default]);
} else if (name.compare(0, 6, "style.") == 0 && name.length() > 6) {
- const ClassID class_id = ClassDictionary::Lookup(name.substr(6));
+ const ClassID class_id = ClassDictionary::Get().lookup(name.substr(6));
parseStyle(replaceConstant(itr->value), styles[class_id]);
}
}