Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TaggedScheduler, couple lifetime of tasks and orchestrator #2398

Merged
merged 34 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
82a1c18
Add TaggedScheduler
mwilsnd Jun 5, 2024
98832ea
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2024
28bdfbf
Clean up metal renderer backend
mwilsnd Jun 5, 2024
a2fcb01
Migrate raster/DEM to TaggedScheduler
mwilsnd Jun 6, 2024
ad39e92
Update threadPool usage in style test
mwilsnd Jun 6, 2024
ace7cd1
Add threadPool to tile params in custom tile test
mwilsnd Jun 6, 2024
2c9e200
Unused parameter
mwilsnd Jun 6, 2024
2df65fa
Geojson test
mwilsnd Jun 6, 2024
99cf7cb
Raster tile tests
mwilsnd Jun 6, 2024
5fc3b79
Vector tile test
mwilsnd Jun 6, 2024
c6b6276
Track the total number of pending tasks
mwilsnd Jun 10, 2024
e4e3972
Merge branch 'main' into scheduler-lifetimes
mwilsnd Jun 11, 2024
056423f
Merge branch 'main' into scheduler-lifetimes
mwilsnd Jun 11, 2024
e80cdd4
Merge branch 'main' into scheduler-lifetimes
louwers Jun 12, 2024
41afaa1
Merge branch 'main' into scheduler-lifetimes
louwers Jun 20, 2024
3afb348
Replace void* with SimpleIdentity
louwers Jun 20, 2024
456f57f
Update Qt to mbgl::util::SimpleIdentity
louwers Jun 20, 2024
0432ee3
Fix C++ unit tests
louwers Jun 20, 2024
a90548c
Fix smoke test
mwilsnd Jun 20, 2024
0e97700
Sprite loader, GeoJSON and Style are scheduler-aware
mwilsnd Jun 24, 2024
a692063
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 24, 2024
b7ab12b
Merge branch 'main' into scheduler-lifetimes
mwilsnd Jun 24, 2024
21362fd
Fix platforms
mwilsnd Jun 24, 2024
1807147
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 24, 2024
d9d6c16
Use generic background queue for loading GeoJSON sources
mwilsnd Jun 25, 2024
79f19fc
Make TileCache wait on all background deferred tasks at destruction
mwilsnd Jun 26, 2024
3202788
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2024
e51d9e1
Fix `SimpleIdentity::isEmpty`, increment `runningCount` early
mwilsnd Jun 26, 2024
ec1654d
Create the thread pool before the renderer backend on Android
mwilsnd Jun 26, 2024
ed34456
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2024
ad914f2
Don't use condition_variable_any/shared_mutex in tile cache
mwilsnd Jun 26, 2024
5dd1937
Add a test for concurrent pool tag execution
mwilsnd Jun 26, 2024
d4cf974
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 26, 2024
2f9e9c4
Stray comment, clean up tile cache
mwilsnd Jun 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/mbgl/actor/actor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

namespace mbgl {

class TaggedScheduler;

/**
An `Actor<O>` is an owning reference to an asynchronous object of type `O`:
an "actor". Communication with an actor happens via message passing: you send
Expand Down Expand Up @@ -61,6 +63,11 @@ class Actor {
Actor(Scheduler& scheduler, Args&&... args)
: target(scheduler, parent, std::forward<Args>(args)...) {}

template <class... Args>
Actor(const TaggedScheduler& scheduler, Args&&... args)
: retainer(scheduler.get()),
target(scheduler, parent, std::forward<Args>(args)...) {}

template <class... Args>
Actor(std::shared_ptr<Scheduler> scheduler, Args&&... args)
: retainer(std::move(scheduler)),
Expand Down
16 changes: 16 additions & 0 deletions include/mbgl/actor/established_actor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ class EstablishedActor {
parent.mailbox->open(scheduler);
}

// Construct the Object from a parameter pack `args` (i.e. `Object(args...)`)
template <typename U = Object,
class... Args,
typename std::enable_if_t<std::is_constructible_v<U, Args...> ||
std::is_constructible_v<U, ActorRef<U>, Args...>>* = nullptr>
EstablishedActor(const TaggedScheduler& scheduler, AspiringActor<Object>& parent_, Args&&... args)
: parent(parent_) {
emplaceObject(std::forward<Args>(args)...);
parent.mailbox->open(scheduler);
}

// Construct the `Object` from a tuple containing the constructor arguments
// (i.e. `Object(std::get<0>(args), std::get<1>(args), ...)`)
template <class ArgsTuple, std::size_t ArgCount = std::tuple_size<std::decay_t<ArgsTuple>>::value>
Expand All @@ -48,6 +59,11 @@ class EstablishedActor {
parent.mailbox->open(scheduler);
}

template <class ArgsTuple, std::size_t ArgCount = std::tuple_size<std::decay_t<ArgsTuple>>::value>
EstablishedActor(const TaggedScheduler& scheduler, AspiringActor<Object>& parent_, ArgsTuple&& args) {
EstablishedActor(*scheduler.get(), parent_, std::forward<ArgsTuple>(args));
}

EstablishedActor(const EstablishedActor&) = delete;

~EstablishedActor() {
Expand Down
6 changes: 5 additions & 1 deletion include/mbgl/actor/mailbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <queue>

#include <mapbox/std/weak.hpp>
#include <mbgl/actor/scheduler.hpp>

namespace mbgl {

Expand All @@ -21,11 +22,13 @@ class Mailbox : public std::enable_shared_from_this<Mailbox> {
Mailbox();

Mailbox(Scheduler&);
Mailbox(const TaggedScheduler&);

/// Attach the given scheduler to this mailbox and begin processing messages
/// sent to it. The mailbox must be a "holding" mailbox, as created by the
/// default constructor Mailbox().
void open(Scheduler& scheduler_);
void open(const TaggedScheduler& scheduler_);
void open(Scheduler&);
void close();

// Indicate this mailbox will no longer be checked for messages
Expand All @@ -46,6 +49,7 @@ class Mailbox : public std::enable_shared_from_this<Mailbox> {
Abandoned
};

util::SimpleIdentity schedulerTag = util::SimpleIdentity::Empty;
mapbox::base::WeakPtr<Scheduler> weakScheduler;

std::recursive_mutex receivingMutex;
Expand Down
66 changes: 50 additions & 16 deletions include/mbgl/actor/scheduler.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <mbgl/util/chrono.hpp>
#include <mbgl/util/identity.hpp>

#include <mapbox/std/weak.hpp>

Expand Down Expand Up @@ -39,12 +40,17 @@ class Scheduler {

/// Enqueues a function for execution.
virtual void schedule(std::function<void()>&&) = 0;
virtual void schedule(const util::SimpleIdentity, std::function<void()>&&) = 0;

/// Makes a weak pointer to this Scheduler.
virtual mapbox::base::WeakPtr<Scheduler> makeWeakPtr() = 0;
/// Enqueues a function for execution on the render thread.
virtual void runOnRenderThread(std::function<void()>&&) {};
virtual void runRenderJobs() {}

/// Enqueues a function for execution on the render thread owned by the given tag.
virtual void runOnRenderThread(const util::SimpleIdentity, std::function<void()>&&) {}
/// Run render thread jobs for the given tag
/// @param tag Tag of owner
/// @param closeQueue Runs all render jobs and then removes the internal queue.
virtual void runRenderJobs([[maybe_unused]] const util::SimpleIdentity tag,
[[maybe_unused]] bool closeQueue = false) {}
/// Returns a closure wrapping the given one.
///
/// When the returned closure is invoked for the first time, it schedules
Expand All @@ -62,15 +68,14 @@ class Scheduler {
/// The |TaskFn| return type must be compatible with the |ReplyFn| argument
/// type. Note: the task result is copied and passed by value.
template <typename TaskFn, typename ReplyFn>
void scheduleAndReplyValue(const TaskFn& task, const ReplyFn& reply) {
void scheduleAndReplyValue(const util::SimpleIdentity tag, TaskFn&& task, ReplyFn&& reply) {
assert(GetCurrent());
scheduleAndReplyValue(task, reply, GetCurrent()->makeWeakPtr());
scheduleAndReplyValue(tag, task, reply, GetCurrent()->makeWeakPtr());
}

/// Wait until there's nothing pending or in process
/// Must not be called from a task provided to this scheduler.
/// @param timeout Time to wait, or zero to wait forever.
virtual std::size_t waitForEmpty(Milliseconds timeout = Milliseconds{0}) = 0;
virtual void waitForEmpty(const util::SimpleIdentity = util::SimpleIdentity::Empty) = 0;

/// Set/Get the current Scheduler for this thread
static Scheduler* GetCurrent();
Expand Down Expand Up @@ -99,21 +104,50 @@ class Scheduler {

protected:
template <typename TaskFn, typename ReplyFn>
void scheduleAndReplyValue(const TaskFn& task,
void scheduleAndReplyValue(const util::SimpleIdentity tag,
const TaskFn& task,
const ReplyFn& reply,
mapbox::base::WeakPtr<Scheduler> replyScheduler) {
auto scheduled = [replyScheduler = std::move(replyScheduler), task, reply] {
schedule(tag, [replyScheduler = std::move(replyScheduler), tag, task, reply] {
auto lock = replyScheduler.lock();
if (!replyScheduler) return;
auto scheduledReply = [reply, result = task()] {
reply(result);
};
replyScheduler->schedule(std::move(scheduledReply));
};
schedule(std::move(scheduled));
replyScheduler->schedule(tag, [reply, result = task()] { reply(result); });
});
}

std::function<void(const std::exception_ptr)> handler;
};

/// @brief A TaggedScheduler pairs a scheduler with an identifier. Tasklets submitted via a TaggedScheduler
/// are bucketed with the tag to enable queries on tasks related to that tag. This allows multiple map
/// instances to all use the same scheduler and await processing of all their tasks prior to map deletion.
class TaggedScheduler {
public:
TaggedScheduler() = delete;
TaggedScheduler(std::shared_ptr<Scheduler> scheduler_, const util::SimpleIdentity tag_)
: tag(tag_),
scheduler(std::move(scheduler_)) {}
TaggedScheduler(const TaggedScheduler&) = default;

/// @brief Get the wrapped scheduler
/// @return
const std::shared_ptr<Scheduler>& get() const noexcept { return scheduler; }

void schedule(std::function<void()>&& fn) { scheduler->schedule(tag, std::move(fn)); }
void runOnRenderThread(std::function<void()>&& fn) { scheduler->runOnRenderThread(tag, std::move(fn)); }
void runRenderJobs(bool closeQueue = false) { scheduler->runRenderJobs(tag, closeQueue); }
void waitForEmpty() const noexcept { scheduler->waitForEmpty(tag); }

/// type. Note: the task result is copied and passed by value.
template <typename TaskFn, typename ReplyFn>
void scheduleAndReplyValue(TaskFn&& task, ReplyFn&& reply) {
scheduler->scheduleAndReplyValue(tag, task, reply);
}

const mbgl::util::SimpleIdentity tag;

private:
std::shared_ptr<Scheduler> scheduler;
};

} // namespace mbgl
5 changes: 1 addition & 4 deletions include/mbgl/gfx/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ using VertexAttributeArrayPtr = std::shared_ptr<VertexAttributeArray>;
class Context {
protected:
Context(uint32_t maximumVertexBindingCount_)
: maximumVertexBindingCount(maximumVertexBindingCount_),
backgroundScheduler(Scheduler::GetBackground()) {}
: maximumVertexBindingCount(maximumVertexBindingCount_) {}

public:
static constexpr const uint32_t minimumRequiredVertexBindingCount = 8;
Expand Down Expand Up @@ -174,8 +173,6 @@ class Context {
virtual std::unique_ptr<DrawScopeResource> createDrawScopeResource() = 0;

gfx::RenderingStats stats;

std::shared_ptr<Scheduler> backgroundScheduler;
};

} // namespace gfx
Expand Down
8 changes: 8 additions & 0 deletions include/mbgl/gfx/renderer_backend.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/util.hpp>

#include <memory>
Expand All @@ -8,6 +9,7 @@
namespace mbgl {

class ProgramParameters;
class Map;

namespace gfx {

Expand All @@ -25,12 +27,16 @@ enum class ContextMode : bool {
class RendererBackend {
protected:
explicit RendererBackend(ContextMode);
RendererBackend(ContextMode, const TaggedScheduler&);

public:
virtual ~RendererBackend();
RendererBackend(const RendererBackend&) = delete;
RendererBackend& operator=(const RendererBackend&) = delete;

// Return the background thread pool assigned to this backend
TaggedScheduler& getThreadPool() noexcept { return threadPool; }

/// Returns the device's context.
Context& getContext();

Expand All @@ -48,6 +54,7 @@ class RendererBackend {
/// One-time shader initialization
virtual void initShaders(gfx::ShaderRegistry&, const ProgramParameters&) = 0;
#endif
const mbgl::util::SimpleIdentity uniqueID;

protected:
virtual std::unique_ptr<Context> createContext() = 0;
Expand All @@ -70,6 +77,7 @@ class RendererBackend {
std::unique_ptr<Context> context;
const ContextMode contextMode;
std::once_flag initialized;
TaggedScheduler threadPool;

friend class BackendScope;
};
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/gl/renderer_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ using FramebufferID = uint32_t;
class RendererBackend : public gfx::RendererBackend {
public:
RendererBackend(gfx::ContextMode);
RendererBackend(gfx::ContextMode, const TaggedScheduler&);
~RendererBackend() override;

/// Called prior to rendering to update the internally assumed OpenGL state.
Expand Down
3 changes: 3 additions & 0 deletions include/mbgl/renderer/renderer_frontend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <mbgl/gfx/drawable.hpp>
#endif

#include <mbgl/actor/scheduler.hpp>
#include <memory>

namespace mbgl {
Expand All @@ -30,6 +31,8 @@ class RendererFrontend {
/// Coalescing updates is up to the implementer
virtual void update(std::shared_ptr<UpdateParameters>) = 0;

virtual const TaggedScheduler& getThreadPool() const = 0;

protected:
};

Expand Down
3 changes: 1 addition & 2 deletions include/mbgl/style/sources/geojson_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class GeoJSONData {
using TileFeatures = mapbox::feature::feature_collection<int16_t>;
using Features = mapbox::feature::feature_collection<double>;
static std::shared_ptr<GeoJSONData> create(const GeoJSON&,
std::shared_ptr<Scheduler> scheduler,
std::shared_ptr<Scheduler> sequencedScheduler,
const Immutable<GeoJSONOptions>& = GeoJSONOptions::defaultOptions());

virtual ~GeoJSONData() = default;
Expand Down Expand Up @@ -80,7 +80,6 @@ class GeoJSONSource final : public Source {
private:
std::optional<std::string> url;
std::unique_ptr<AsyncRequest> req;
std::shared_ptr<Scheduler> threadPool;
std::shared_ptr<Scheduler> sequencedScheduler;
mapbox::base::WeakPtrFactory<Source> weakFactory{this};
// Do not add members here, see `WeakPtrFactory`
Expand Down
3 changes: 2 additions & 1 deletion include/mbgl/style/style.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <mbgl/actor/scheduler.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/transition_options.hpp>
Expand All @@ -22,7 +23,7 @@ class Layer;

class Style {
public:
Style(std::shared_ptr<FileSource>, float pixelRatio);
Style(std::shared_ptr<FileSource>, float pixelRatio, const TaggedScheduler& threadPool_);
~Style();

void loadJSON(const std::string&);
Expand Down
9 changes: 8 additions & 1 deletion include/mbgl/util/identity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class SimpleIdentity final {
bool operator!=(const SimpleIdentity& other) const noexcept { return uniqueID != other.uniqueID; }

std::int64_t id() const noexcept { return uniqueID; }
bool isEmpty() const noexcept { return uniqueID != emptyID; }
bool isEmpty() const noexcept { return uniqueID == emptyID; }

operator bool() const noexcept { return isEmpty(); }
bool operator!() const noexcept { return !isEmpty(); }
Expand Down Expand Up @@ -58,3 +58,10 @@ inline std::string toString(const util::SimpleIdentity& ident) {

} // namespace util
} // namespace mbgl

template <>
struct std::hash<mbgl::util::SimpleIdentity> {
std::size_t operator()(const mbgl::util::SimpleIdentity& s) const noexcept {
return std::hash<std::int64_t>{}(s.id());
}
};
3 changes: 2 additions & 1 deletion include/mbgl/util/run_loop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ class RunLoop : public Scheduler, private util::noncopyable {
}

void schedule(std::function<void()>&& fn) override { invoke(std::move(fn)); }
void schedule(const util::SimpleIdentity, std::function<void()>&& fn) override { schedule(std::move(fn)); }
::mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }

std::size_t waitForEmpty(Milliseconds timeout) override;
void waitForEmpty(const util::SimpleIdentity = util::SimpleIdentity::Empty) override;

class Impl;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
AndroidRendererBackend& backend;
};

AndroidRendererBackend::AndroidRendererBackend()
AndroidRendererBackend::AndroidRendererBackend(const TaggedScheduler& threadPool)
: gl::RendererBackend(gfx::ContextMode::Unique),
mbgl::gfx::Renderable({64, 64}, std::make_unique<AndroidGLRenderableResource>(*this)) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace android {

class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
public:
AndroidRendererBackend();
AndroidRendererBackend(const TaggedScheduler& threadPool);
~AndroidRendererBackend() override;

void updateViewPort();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
updateAsyncTask->send();
}

const TaggedScheduler& AndroidRendererFrontend::getThreadPool() const {
return mapRenderer.getThreadPool();
}

void AndroidRendererFrontend::reduceMemoryUse() {
mapRenderer.actor().invoke(&Renderer::reduceMemoryUse);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class AndroidRendererFrontend : public RendererFrontend {

void update(std::shared_ptr<UpdateParameters>) override;

const TaggedScheduler& getThreadPool() const override;

// Feature querying
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
Expand Down
Loading
Loading