add more locking around GlyphStore and FontStack
this is a stopgap until we have a solution that gives every worker thread their own copy
This commit is contained in:
@@ -60,6 +60,39 @@ private:
|
||||
rwlock *mtx = nullptr;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class exclusive {
|
||||
public:
|
||||
exclusive(T& val, mutex &mtx) : ptr(&val), lock(mtx) {}
|
||||
exclusive(T *val, mutex &mtx) : ptr(val), lock(mtx) {}
|
||||
exclusive(mutex &mtx) : lock(mtx) {}
|
||||
exclusive(const std::unique_ptr<mutex> &mtx) : lock(mtx) {}
|
||||
exclusive(const exclusive &) = delete;
|
||||
exclusive(exclusive &&) = default;
|
||||
exclusive &operator=(const exclusive &) = delete;
|
||||
exclusive &operator=(exclusive &&) = default;
|
||||
|
||||
T *operator->() { return ptr; }
|
||||
const T *operator->() const { return ptr; }
|
||||
T *operator*() { return ptr; }
|
||||
const T *operator*() const { return ptr; }
|
||||
operator T&() { return *ptr; }
|
||||
operator const T&() const { return *ptr; }
|
||||
|
||||
void operator<<(T& val) { operator<<(&val); }
|
||||
void operator<<(T *val) {
|
||||
if (ptr) {
|
||||
throw std::runtime_error("exclusive<> was assigned before");
|
||||
}
|
||||
ptr = val;
|
||||
}
|
||||
|
||||
private:
|
||||
T *ptr = nullptr;
|
||||
lock lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const char *getFileRequestError(uv_fs_t *req);
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
if (layout.text.justify == TextJustifyType::Right) justify = 1;
|
||||
else if (layout.text.justify == TextJustifyType::Left) justify = 0;
|
||||
|
||||
const FontStack &fontStack = glyphStore.getFontStack(layout.text.font);
|
||||
const auto &fontStack = glyphStore.getFontStack(layout.text.font);
|
||||
|
||||
for (const SymbolFeature &feature : features) {
|
||||
if (!feature.geometry.size()) continue;
|
||||
@@ -183,7 +183,7 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
|
||||
// if feature has text, shape the text
|
||||
if (feature.label.length()) {
|
||||
shaping = fontStack.getShaping(
|
||||
shaping = fontStack->getShaping(
|
||||
/* string */ feature.label,
|
||||
/* maxWidth: ems */ layout.text.max_width * 24,
|
||||
/* lineHeight: ems */ layout.text.line_height * 24,
|
||||
|
||||
@@ -223,7 +223,7 @@ void GlyphPBF::parse(FontStack &stack) {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
GlyphStore::GlyphStore(FileSource& fileSource_) : fileSource(fileSource_) {}
|
||||
GlyphStore::GlyphStore(FileSource& fileSource_) : fileSource(fileSource_), mtx(util::make_unique<uv::mutex>()) {}
|
||||
|
||||
void GlyphStore::setURL(const std::string &url) {
|
||||
glyphURL = url;
|
||||
@@ -237,15 +237,14 @@ void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set
|
||||
return;
|
||||
}
|
||||
|
||||
FontStack *stack = nullptr;
|
||||
uv::exclusive<FontStack> stack(mtx);
|
||||
|
||||
std::vector<std::shared_future<GlyphPBF &>> futures;
|
||||
futures.reserve(glyphRanges.size());
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
auto &rangeSets = ranges[fontStack];
|
||||
|
||||
stack = &createFontStack(fontStack);
|
||||
stack << createFontStack(fontStack);
|
||||
|
||||
// Attempt to load the glyph range. If the GlyphSet already exists, we are getting back
|
||||
// the same shared_future.
|
||||
@@ -258,7 +257,7 @@ void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set
|
||||
// When we get a result (or the GlyphSet is aready loaded), we are attempting to parse the
|
||||
// GlyphSet.
|
||||
for (std::shared_future<GlyphPBF &> &future : futures) {
|
||||
future.get().parse(*stack);
|
||||
future.get().parse(stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,12 +276,14 @@ FontStack &GlyphStore::createFontStack(const std::string &fontStack) {
|
||||
if (stack_it == stacks.end()) {
|
||||
stack_it = stacks.emplace(fontStack, util::make_unique<FontStack>()).first;
|
||||
}
|
||||
|
||||
return *stack_it->second.get();
|
||||
}
|
||||
|
||||
FontStack &GlyphStore::getFontStack(const std::string &fontStack) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
return createFontStack(fontStack);
|
||||
uv::exclusive<FontStack> GlyphStore::getFontStack(const std::string &fontStack) {
|
||||
uv::exclusive<FontStack> stack(mtx);
|
||||
stack << createFontStack(fontStack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@@ -76,7 +77,7 @@ public:
|
||||
// Block until all specified GlyphRanges of the specified font stack are loaded.
|
||||
void waitForGlyphRanges(const std::string &fontStack, const std::set<GlyphRange> &glyphRanges);
|
||||
|
||||
FontStack &getFontStack(const std::string &fontStack);
|
||||
uv::exclusive<FontStack> getFontStack(const std::string &fontStack);
|
||||
|
||||
void setURL(const std::string &url);
|
||||
|
||||
@@ -90,7 +91,7 @@ private:
|
||||
FileSource& fileSource;
|
||||
std::unordered_map<std::string, std::map<GlyphRange, std::unique_ptr<GlyphPBF>>> ranges;
|
||||
std::unordered_map<std::string, std::unique_ptr<FontStack>> stacks;
|
||||
std::mutex mtx;
|
||||
std::unique_ptr<uv::mutex> mtx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user