diff options
Diffstat (limited to 'include/mbgl/util')
-rw-r--r-- | include/mbgl/util/constants.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/util/convert.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/util/image.hpp | 49 | ||||
-rw-r--r-- | include/mbgl/util/immutable.hpp | 133 | ||||
-rw-r--r-- | include/mbgl/util/indexed_tuple.hpp | 7 | ||||
-rw-r--r-- | include/mbgl/util/interpolate.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/util/noncopyable.hpp | 8 | ||||
-rw-r--r-- | include/mbgl/util/projection.hpp | 22 | ||||
-rw-r--r-- | include/mbgl/util/range.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/util/run_loop.hpp | 21 | ||||
-rw-r--r-- | include/mbgl/util/size.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/util/string.hpp | 25 | ||||
-rw-r--r-- | include/mbgl/util/thread.hpp | 161 | ||||
-rw-r--r-- | include/mbgl/util/tileset.hpp | 19 | ||||
-rw-r--r-- | include/mbgl/util/unitbezier.hpp | 8 | ||||
-rw-r--r-- | include/mbgl/util/util.hpp | 7 | ||||
-rw-r--r-- | include/mbgl/util/work_task.hpp | 3 | ||||
-rw-r--r-- | include/mbgl/util/work_task_impl.hpp | 44 |
18 files changed, 445 insertions, 90 deletions
diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp index dbc4bddde5..d5e55065c4 100644 --- a/include/mbgl/util/constants.hpp +++ b/include/mbgl/util/constants.hpp @@ -38,10 +38,13 @@ constexpr double MIN_ZOOM = 0.0; constexpr double MAX_ZOOM = 25.5; constexpr float MIN_ZOOM_F = MIN_ZOOM; constexpr float MAX_ZOOM_F = MAX_ZOOM; +constexpr uint8_t DEFAULT_MAX_ZOOM = 22; + +constexpr uint8_t DEFAULT_PREFETCH_ZOOM_DELTA = 4; constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; -constexpr Duration DEFAULT_FADE_DURATION = Milliseconds(300); +constexpr Duration DEFAULT_TRANSITION_DURATION = Milliseconds(300); constexpr Seconds CLOCK_SKEW_RETRY_TIMEOUT { 30 }; constexpr UnitBezier DEFAULT_TRANSITION_EASE = { 0, 0, 0.25, 1 }; @@ -58,7 +61,6 @@ extern const bool tileParseWarnings; extern const bool styleParseWarnings; extern const bool spriteWarnings; extern const bool renderWarnings; -extern const bool renderTree; extern const bool labelTextMissingWarning; extern const bool missingFontStackWarning; extern const bool missingFontFaceWarning; diff --git a/include/mbgl/util/convert.hpp b/include/mbgl/util/convert.hpp index c2b3d9950d..02ec7feef9 100644 --- a/include/mbgl/util/convert.hpp +++ b/include/mbgl/util/convert.hpp @@ -1,3 +1,5 @@ +#include <mbgl/util/util.hpp> + #include <array> #include <type_traits> #include <utility> @@ -7,8 +9,8 @@ namespace util { template<typename To, typename From, std::size_t Size, typename = std::enable_if_t<std::is_convertible<From, To>::value>> -constexpr std::array<To, Size> convert(const std::array<From, Size>&from) { - std::array<To, Size> to {}; +MBGL_CONSTEXPR std::array<To, Size> convert(const std::array<From, Size>&from) { + std::array<To, Size> to {{}}; std::copy(std::begin(from), std::end(from), std::begin(to)); return to; } diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp index a41b8462bd..4887058f79 100644 --- a/include/mbgl/util/image.hpp +++ b/include/mbgl/util/image.hpp @@ -5,6 +5,7 @@ #include <mbgl/util/size.hpp> #include <string> +#include <cstring> #include <memory> #include <algorithm> @@ -66,9 +67,9 @@ public: template <typename T = Image> T clone() const { - T copy(size); - std::copy(data.get(), data.get() + bytes(), copy.data.get()); - return copy; + T copy_(size); + std::copy(data.get(), data.get() + bytes(), copy_.data.get()); + return copy_; } size_t stride() const { return channels * size.width; } @@ -78,10 +79,52 @@ public: std::fill(data.get(), data.get() + bytes(), value); } + void resize(Size size_) { + if (size == size_) { + return; + } + Image newImage(size_); + newImage.fill(0); + copy(*this, newImage, {0, 0}, {0, 0}, { + std::min(size.width, size_.width), + std::min(size.height, size_.height) + }); + operator=(std::move(newImage)); + } + + // Clears the rect area specified by `pt` and `size` from `dstImage`. + static void clear(Image& dstImg, const Point<uint32_t>& pt, const Size& size) { + if (size.isEmpty()) { + return; + } + + if (!dstImg.valid()) { + throw std::invalid_argument("invalid destination for image clear"); + } + + if (size.width > dstImg.size.width || + size.height > dstImg.size.height || + pt.x > dstImg.size.width - size.width || + pt.y > dstImg.size.height - size.height) { + throw std::out_of_range("out of range destination coordinates for image clear"); + } + + uint8_t* dstData = dstImg.data.get(); + + for (uint32_t y = 0; y < size.height; y++) { + const std::size_t dstOffset = (pt.y + y) * dstImg.stride() + pt.x * channels; + std::memset(dstData + dstOffset, 0, size.width * channels); + } + } + // Copy image data within `rect` from `src` to the rectangle of the same size at `pt` // in `dst`. If the specified bounds exceed the bounds of the source or destination, // throw `std::out_of_range`. Must not be used to move data within a single Image. static void copy(const Image& srcImg, Image& dstImg, const Point<uint32_t>& srcPt, const Point<uint32_t>& dstPt, const Size& size) { + if (size.isEmpty()) { + return; + } + if (!srcImg.valid()) { throw std::invalid_argument("invalid source for image copy"); } diff --git a/include/mbgl/util/immutable.hpp b/include/mbgl/util/immutable.hpp new file mode 100644 index 0000000000..eb26c0d282 --- /dev/null +++ b/include/mbgl/util/immutable.hpp @@ -0,0 +1,133 @@ +#pragma once + +#include <memory> + +namespace mbgl { + +/** + * `Mutable<T>` is a non-nullable uniquely owning reference to a `T`. It can be efficiently converted + * to `Immutable<T>`. + * + * The lifecycle of `Mutable<T>` and `Immutable<T>` is as follows: + * + * 1. Create a `Mutable<T>` using `makeMutable(...)` + * 2. Mutate it freely + * 3. When you're ready to freeze its state and enable safe cross-thread sharing, move assign or + * move construct it to `Immutable<T>` + * + * The reason that `Mutable<T>` exists, rather than simply using a `std::unique_ptr<T>`, is to take advantage + * of the underlying single-allocation optimization provided by `std::make_shared`. + */ +template <class T> +class Mutable { +public: + Mutable(Mutable&&) = default; + Mutable& operator=(Mutable&&) = default; + + Mutable(const Mutable&) = delete; + Mutable& operator=(const Mutable&) = delete; + + T* get() { return ptr.get(); } + T* operator->() { return ptr.get(); } + T& operator*() { return *ptr; } + +private: + Mutable(std::shared_ptr<T>&& s) + : ptr(std::move(s)) {} + + std::shared_ptr<T> ptr; + + template <class S> friend class Immutable; + template <class S, class... Args> friend Mutable<S> makeMutable(Args&&...); +}; + +template <class T, class... Args> +Mutable<T> makeMutable(Args&&... args) { + return Mutable<T>(std::make_shared<T>(std::forward<Args>(args)...)); +} + +/** + * `Immutable<T>` is a non-nullable shared reference to a `const T`. Construction requires + * a transfer of unique ownership from a `Mutable<T>`; once constructed it has the same behavior + * as `std::shared_ptr<const T>` but with better indication of intent. + * + * Normally one should not share state between threads because it's difficult to verify the + * absence of read/write data races. `Immutable` provides a guarantee that no writes are + * possible, and instances therefore can be freely transferred and shared between threads. + */ +template <class T> +class Immutable { +public: + template <class S> + Immutable(Mutable<S>&& s) + : ptr(std::const_pointer_cast<const S>(std::move(s.ptr))) {} + + template <class S> + Immutable(Immutable<S>&& s) + : ptr(std::move(s.ptr)) {} + + template <class S> + Immutable(const Immutable<S>& s) + : ptr(s.ptr) {} + + template <class S> + Immutable& operator=(Mutable<S>&& s) { + ptr = std::const_pointer_cast<const S>(std::move(s.ptr)); + return *this; + } + + template <class S> + Immutable& operator=(Immutable<S>&& s) { + ptr = std::move(s.ptr); + return *this; + } + + template <class S> + Immutable& operator=(const Immutable<S>& s) { + ptr = s.ptr; + return *this; + } + + const T* get() const { return ptr.get(); } + const T* operator->() const { return ptr.get(); } + const T& operator*() const { return *ptr; } + + friend bool operator==(const Immutable<T>& lhs, const Immutable<T>& rhs) { + return lhs.ptr == rhs.ptr; + } + + friend bool operator!=(const Immutable<T>& lhs, const Immutable<T>& rhs) { + return lhs.ptr != rhs.ptr; + } + +private: + Immutable(std::shared_ptr<const T>&& s) + : ptr(std::move(s)) {} + + std::shared_ptr<const T> ptr; + + template <class S> friend class Immutable; + template <class S, class U> friend Immutable<S> staticImmutableCast(const Immutable<U>&); +}; + +template <class S, class U> +Immutable<S> staticImmutableCast(const Immutable<U>& u) { + return Immutable<S>(std::static_pointer_cast<const S>(u.ptr)); +} + +/** + * Constrained mutation of an immutable reference. Makes a temporarily-mutable copy of the + * input Immutable using the inner type's copy constructor, runs the given callable on the + * mutable copy, and then freezes the copy and reassigns it to the input reference. + * + * Note that other Immutables referring to the same inner instance are not affected; they + * continue to referencing the original immutable instance. + */ +template <class T, class Fn> +void mutate(Immutable<T>& immutable, Fn&& fn) { + Mutable<T> mut = makeMutable<T>(*immutable); + std::forward<Fn>(fn)(*mut); + immutable = std::move(mut); +} + +} // namespace mbgl diff --git a/include/mbgl/util/indexed_tuple.hpp b/include/mbgl/util/indexed_tuple.hpp index a414639530..fd0b931d36 100644 --- a/include/mbgl/util/indexed_tuple.hpp +++ b/include/mbgl/util/indexed_tuple.hpp @@ -31,16 +31,13 @@ public: using std::tuple<Ts...>::tuple; template <class I> - static constexpr std::size_t Index = TypeIndex<I, Is...>::value; - - template <class I> auto& get() { - return std::get<Index<I>>(*this); + return std::get<TypeIndex<I, Is...>::value>(*this); } template <class I> const auto& get() const { - return std::get<Index<I>>(*this); + return std::get<TypeIndex<I, Is...>::value>(*this); } template <class... Js, class... Us> diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp index a2103f18b2..6738987598 100644 --- a/include/mbgl/util/interpolate.hpp +++ b/include/mbgl/util/interpolate.hpp @@ -95,7 +95,11 @@ struct Interpolator<std::vector<T>> : Uninterpolated {}; template <class T> -constexpr bool Interpolatable = !std::is_base_of<Uninterpolated, Interpolator<T>>::value; +struct Interpolatable + : std::conditional_t< + !std::is_base_of<Uninterpolated, Interpolator<T>>::value, + std::true_type, + std::false_type> {}; } // namespace util } // namespace mbgl diff --git a/include/mbgl/util/noncopyable.hpp b/include/mbgl/util/noncopyable.hpp index 105a76a9a0..8cb7e198d9 100644 --- a/include/mbgl/util/noncopyable.hpp +++ b/include/mbgl/util/noncopyable.hpp @@ -7,15 +7,17 @@ namespace non_copyable_ class noncopyable { +public: + noncopyable( noncopyable const& ) = delete; + noncopyable& operator=(noncopyable const& ) = delete; + protected: constexpr noncopyable() = default; ~noncopyable() = default; - noncopyable( noncopyable const& ) = delete; - noncopyable& operator=(noncopyable const& ) = delete; }; } // namespace non_copyable_ -typedef non_copyable_::noncopyable noncopyable; +using noncopyable = non_copyable_::noncopyable; } // namespace util } // namespace mbgl diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp index 3cc1146513..f64502c5bc 100644 --- a/include/mbgl/util/projection.hpp +++ b/include/mbgl/util/projection.hpp @@ -75,10 +75,7 @@ public: } static Point<double> project(const LatLng& latLng, double scale) { - return Point<double> { - util::LONGITUDE_MAX + latLng.longitude(), - util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latLng.latitude() * M_PI / util::DEGREES_MAX)) - } * worldSize(scale) / util::DEGREES_MAX; + return project_(latLng, worldSize(scale)); } static LatLng unproject(const Point<double>& p, double scale, LatLng::WrapMode wrapMode = LatLng::Unwrapped) { @@ -89,6 +86,23 @@ public: wrapMode }; } + + // Project lat, lon to point in a zoom-dependent world size + static Point<double> project(const LatLng& point, uint8_t zoom, uint16_t tileSize) { + const double t2z = tileSize * std::pow(2, zoom); + Point<double> pt = project_(point, t2z); + // Flip y coordinate + auto x = std::round(std::min(pt.x, t2z)); + auto y = std::round(std::min(t2z - pt.y, t2z)); + return { x, y }; + } +private: + static Point<double> project_(const LatLng& latLng, double worldSize) { + return Point<double> { + util::LONGITUDE_MAX + latLng.longitude(), + util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latLng.latitude() * M_PI / util::DEGREES_MAX)) + } * worldSize / util::DEGREES_MAX; + } }; } // namespace mbgl diff --git a/include/mbgl/util/range.hpp b/include/mbgl/util/range.hpp index f7fa92eb8b..5591a22a1f 100644 --- a/include/mbgl/util/range.hpp +++ b/include/mbgl/util/range.hpp @@ -1,3 +1,5 @@ +#include <utility> + #pragma once namespace mbgl { @@ -5,8 +7,8 @@ namespace mbgl { template <class T> class Range { public: - constexpr Range(const T& min_, const T& max_) - : min(min_), max(max_) {} + constexpr Range(T min_, T max_) + : min(std::move(min_)), max(std::move(max_)) {} T min; T max; diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp index 5236850d83..acbea80273 100644 --- a/include/mbgl/util/run_loop.hpp +++ b/include/mbgl/util/run_loop.hpp @@ -16,7 +16,7 @@ namespace mbgl { namespace util { -typedef void * LOOP_HANDLE; +using LOOP_HANDLE = void *; class RunLoop : public Scheduler, private util::noncopyable { @@ -62,14 +62,11 @@ public: push(task); return std::make_unique<WorkRequest>(task); } - - // Invoke fn(args...) on this RunLoop, then invoke callback(results...) on the current RunLoop. - template <class Fn, class... Args> - std::unique_ptr<AsyncRequest> - invokeWithCallback(Fn&& fn, Args&&... args) { - std::shared_ptr<WorkTask> task = WorkTask::makeWithCallback(std::forward<Fn>(fn), std::forward<Args>(args)...); - push(task); - return std::make_unique<WorkRequest>(task); + + void schedule(std::weak_ptr<Mailbox> mailbox) override { + invoke([mailbox] () { + Mailbox::maybeReceive(mailbox); + }); } class Impl; @@ -81,12 +78,6 @@ private: void push(std::shared_ptr<WorkTask>); - void schedule(std::weak_ptr<Mailbox> mailbox) override { - invoke([mailbox] () { - Mailbox::maybeReceive(mailbox); - }); - } - void withMutex(std::function<void()>&& fn) { std::lock_guard<std::mutex> lock(mutex); fn(); diff --git a/include/mbgl/util/size.hpp b/include/mbgl/util/size.hpp index 45c303969c..12c0ad056b 100644 --- a/include/mbgl/util/size.hpp +++ b/include/mbgl/util/size.hpp @@ -15,6 +15,10 @@ public: constexpr uint32_t area() const { return width * height; } + + constexpr float aspectRatio() const { + return static_cast<float>(width) / static_cast<float>(height); + } constexpr bool isEmpty() const { return width == 0 || height == 0; diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp index de061647b5..82d317c620 100644 --- a/include/mbgl/util/string.hpp +++ b/include/mbgl/util/string.hpp @@ -1,9 +1,34 @@ #pragma once +#include <sstream> #include <string> #include <cassert> +#include <cstdlib> #include <exception> +// Polyfill needed by Qt when building for Android with GCC +#if defined(__ANDROID__) && defined(__GLIBCXX__) + +namespace std { + +template <typename T> +std::string to_string(T value) +{ + std::ostringstream oss; + oss << value; + + return oss.str(); +} + +inline int stoi(const std::string &str) +{ + return atoi(str.c_str()); +} + +} // namespace std + +#endif + namespace mbgl { namespace util { diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp new file mode 100644 index 0000000000..672eebf6db --- /dev/null +++ b/include/mbgl/util/thread.hpp @@ -0,0 +1,161 @@ +#pragma once + +#include <mbgl/actor/actor.hpp> +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/actor/scheduler.hpp> +#include <mbgl/util/platform.hpp> +#include <mbgl/util/run_loop.hpp> +#include <mbgl/util/util.hpp> + +#include <cassert> +#include <future> +#include <memory> +#include <mutex> +#include <queue> +#include <string> +#include <thread> +#include <utility> + +namespace mbgl { +namespace util { + +// Manages a thread with `Object`. + +// Upon creation of this object, it launches a thread and creates an object of type `Object` +// in that thread. When the `Thread<>` object is destructed, the destructor waits +// for thread termination. The `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. The thread created will always have low priority on +// the platforms that support setting thread priority. +// +// The following properties make this class different from `ThreadPool`: +// +// - Only one thread is created. +// - `Object` will live in a single thread, providing thread affinity. +// - It is safe to use `ThreadLocal` in an `Object` managed by `Thread<>` +// - A `RunLoop` is created for the `Object` thread. +// - `Object` can use `Timer` and do asynchronous I/O, like wait for sockets events. +// +template<class Object> +class Thread : public Scheduler { +public: + template <class... Args> + Thread(const std::string& name, Args&&... args) { + std::promise<void> running; + + thread = std::thread([&] { + platform::setCurrentThreadName(name); + platform::makeThreadLowPriority(); + + util::RunLoop loop_(util::RunLoop::Type::New); + loop = &loop_; + + object = std::make_unique<Actor<Object>>(*this, std::forward<Args>(args)...); + running.set_value(); + + loop->run(); + loop = nullptr; + }); + + running.get_future().get(); + } + + ~Thread() override { + if (paused) { + resume(); + } + + std::promise<void> joinable; + + // Kill the actor, so we don't get more + // messages posted on this scheduler after + // we delete the RunLoop. + loop->invoke([&] { + object.reset(); + joinable.set_value(); + }); + + joinable.get_future().get(); + + loop->stop(); + thread.join(); + } + + // Returns a non-owning reference to `Object` that + // can be used to send messages to `Object`. It is safe + // to the non-owning reference to outlive this object + // and be used after the `Thread<>` gets destroyed. + ActorRef<std::decay_t<Object>> actor() const { + return object->self(); + } + + // Pauses the `Object` thread. It will prevent the object to wake + // up from events such as timers and file descriptor I/O. Messages + // sent to a paused `Object` will be queued and only processed after + // `resume()` is called. + void pause() { + MBGL_VERIFY_THREAD(tid); + + assert(!paused); + + paused = std::make_unique<std::promise<void>>(); + resumed = std::make_unique<std::promise<void>>(); + + auto pausing = paused->get_future(); + + loop->invoke([this] { + auto resuming = resumed->get_future(); + paused->set_value(); + resuming.get(); + }); + + pausing.get(); + } + + // Resumes the `Object` thread previously paused by `pause()`. + void resume() { + MBGL_VERIFY_THREAD(tid); + + assert(paused); + + resumed->set_value(); + + resumed.reset(); + paused.reset(); + } + +private: + MBGL_STORE_THREAD(tid); + + void schedule(std::weak_ptr<Mailbox> mailbox) override { + { + std::lock_guard<std::mutex> lock(mutex); + queue.push(mailbox); + } + + loop->invoke([this] { receive(); }); + } + + void receive() { + std::unique_lock<std::mutex> lock(mutex); + + auto mailbox = queue.front(); + queue.pop(); + lock.unlock(); + + Mailbox::maybeReceive(mailbox); + } + + std::mutex mutex; + std::queue<std::weak_ptr<Mailbox>> queue; + std::thread thread; + std::unique_ptr<Actor<Object>> object; + + std::unique_ptr<std::promise<void>> paused; + std::unique_ptr<std::promise<void>> resumed; + + util::RunLoop* loop = nullptr; +}; + +} // namespace util +} // namespace mbgl diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp index 1f28a5039a..61aa47d4ea 100644 --- a/include/mbgl/util/tileset.hpp +++ b/include/mbgl/util/tileset.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/util/range.hpp> +#include <mbgl/util/constants.hpp> #include <vector> #include <string> @@ -13,11 +14,25 @@ public: enum class Scheme : bool { XYZ, TMS }; std::vector<std::string> tiles; - Range<uint8_t> zoomRange { 0, 22 }; + Range<uint8_t> zoomRange; std::string attribution; - Scheme scheme = Scheme::XYZ; + Scheme scheme; + + Tileset(std::vector<std::string> tiles_ = std::vector<std::string>(), + Range<uint8_t> zoomRange_ = { 0, util::DEFAULT_MAX_ZOOM }, + std::string attribution_ = {}, + Scheme scheme_ = Scheme::XYZ) + : tiles(std::move(tiles_)), + zoomRange(std::move(zoomRange_)), + attribution(std::move(attribution_)), + scheme(scheme_) {} // TileJSON also includes center, zoom, and bounds, but they are not used by mbgl. + + friend bool operator==(const Tileset& lhs, const Tileset& rhs) { + return std::tie(lhs.tiles, lhs.zoomRange, lhs.attribution, lhs.scheme) + == std::tie(rhs.tiles, rhs.zoomRange, rhs.attribution, rhs.scheme); + } }; } // namespace mbgl diff --git a/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp index 3a4994917b..6e644e2d1f 100644 --- a/include/mbgl/util/unitbezier.hpp +++ b/include/mbgl/util/unitbezier.hpp @@ -34,11 +34,11 @@ struct UnitBezier { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). constexpr UnitBezier(double p1x, double p1y, double p2x, double p2y) : cx(3.0 * p1x) - , bx(3.0 * (p2x - p1x) - cx) - , ax(1.0 - cx - bx) + , bx(3.0 * (p2x - p1x) - (3.0 * p1x)) + , ax(1.0 - (3.0 * p1x) - (3.0 * (p2x - p1x) - (3.0 * p1x))) , cy(3.0 * p1y) - , by(3.0 * (p2y - p1y) - cy) - , ay(1.0 - cy - by) { + , by(3.0 * (p2y - p1y) - (3.0 * p1y)) + , ay(1.0 - (3.0 * p1y) - (3.0 * (p2y - p1y) - (3.0 * p1y))) { } double sampleCurveX(double t) const { diff --git a/include/mbgl/util/util.hpp b/include/mbgl/util/util.hpp index c5a7cb3780..7960b40299 100644 --- a/include/mbgl/util/util.hpp +++ b/include/mbgl/util/util.hpp @@ -12,3 +12,10 @@ #define MBGL_VERIFY_THREAD(tid) #endif + +// GCC 4.9 compatibility +#if !defined(__GNUC__) || __GNUC__ >= 5 +#define MBGL_CONSTEXPR constexpr +#else +#define MBGL_CONSTEXPR inline +#endif diff --git a/include/mbgl/util/work_task.hpp b/include/mbgl/util/work_task.hpp index dda8e5d00f..f2dcfcfe86 100644 --- a/include/mbgl/util/work_task.hpp +++ b/include/mbgl/util/work_task.hpp @@ -18,9 +18,6 @@ public: template <class Fn, class... Args> static std::shared_ptr<WorkTask> make(Fn&&, Args&&...); - - template <class Fn, class... Args> - static std::shared_ptr<WorkTask> makeWithCallback(Fn&&, Args&&...); }; } // namespace mbgl diff --git a/include/mbgl/util/work_task_impl.hpp b/include/mbgl/util/work_task_impl.hpp index 8ebc7d45f8..276e0d6237 100644 --- a/include/mbgl/util/work_task_impl.hpp +++ b/include/mbgl/util/work_task_impl.hpp @@ -62,48 +62,4 @@ std::shared_ptr<WorkTask> WorkTask::make(Fn&& fn, Args&&... args) { flag); } -namespace detail { -template <class Tuple, size_t... Indexes> -auto packageArgumentsAndCallback(std::shared_ptr<std::atomic<bool>> flag, - Tuple&& args, - std::index_sequence<Indexes...>) { - auto callback = std::get<sizeof...(Indexes)>(args); - - // Create a lambda L1 that invokes another lambda L2 on the current RunLoop R, that calls - // the callback C. Both lambdas check the flag before proceeding. L1 needs to check the flag - // because if the request was cancelled, then R might have been destroyed. L2 needs to check - // the flag because the request may have been cancelled after L2 was invoked but before it - // began executing. - - auto l2 = [flag, callback] (auto&&... results) { - if (!*flag) { - callback(std::forward<decltype(results)>(results)...); - } - }; - - auto l1 = [flag, current = util::RunLoop::Get(), l2_ = l2] (auto&&... results) { - if (!*flag) { - current->invoke(l2_, std::forward<decltype(results)>(results)...); - } - }; - - return std::make_tuple(std::get<Indexes>(std::forward<Tuple>(args))..., l1); -} -} // namespace detail - -template <class Fn, class... Args> -std::shared_ptr<WorkTask> WorkTask::makeWithCallback(Fn&& fn, Args&&... args) { - auto flag = std::make_shared<std::atomic<bool>>(); - *flag = false; - - auto tuple = detail::packageArgumentsAndCallback(flag, - std::forward_as_tuple(std::forward<Args>(args)...), - std::make_index_sequence<sizeof...(Args) - 1>()); - - return std::make_shared<WorkTaskImpl<std::decay_t<Fn>, decltype(tuple)>>( - std::forward<Fn>(fn), - std::move(tuple), - flag); -} - } // namespace mbgl |