-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Convert DefaultFileSource and dependents to actor model #7678
Conversation
… low priority adds parity with util::Thread
…uction this is a preparatory commit; the Scheduler is currently unused
@kkaefer, thanks for your PR! By analyzing this pull request, we identified @jfirebaugh, @tmpsantos and @1ec5 to be potential reviewers. |
The long term goal is to move the other FileSources onto the actor model as well, which enables us to remove |
I gave this a shot once and I got stuck. The main problem I faced when removing We probably need a new scheduler that is not |
#pragma mark - Internal | ||
|
||
+ (instancetype)sharedPool { | ||
if (NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unnecessary, since there won't be an offline storage object if we're rendering for IB, and even if we were, spinning up this thread pool should be cheap. The reason we do this in MGLOfflineStorage and MGLAccountManager is to avoid potentially expensive operations that may block MGLMapView from rendering within the allotted time.
@interface MGLThreadPool : NSObject | ||
@end | ||
|
||
@interface MGLThreadPool (Private) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a class extension, since the whole header is already internal to the project. A class extension would need to go in a separate header from the public header anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks; as per the comment above, I'm planning on removing MGLThreadPool
altogether, since it's a singleton anyway.
@jfirebaugh given that you're most familiar with this system, could you please do a quick review of whether I'm moving into the right direction with this? |
The way I would model this is to make the request and response callback both first-class actors: class RequestCallback {
public:
// This class exists only to accept and ignore the "self" argument. Maybe it should be optional?
RequestCallback(ActorRef<RequestCallback>, std::function<void (Response)>);
void operator() (Response response) { callback(response); }
private:
std::function<void (Response)> callback;
};
class AssetRequest {
public:
AssetRequest(ActorRef<AssetRequest>);
~AssetRequest(); // cancels
void send(const Resource& resource, ActorRef<RequestCallback> callback) {
// do whatever, then eventually:
callback.invoke(&RequestCallback::operator(), response);
}
};
class SomeClass {
public:
SomeClass(Scheduler& requestScheduler)
: request(requestScheduler) {}
private:
void requestingMethod() {
request.invoke(&AssetRequest::send, resource, callback);
}
void receivingMethod(Response);
Actor<AssetRequest> request;
Actor<RequestCallback> callback {
*util::RunLoop::Get(),
std::bind(&SomeClass::receivingMethod, this)
};
}; |
Stale. |
Getting started on #6426. This is still a work in progress.
A few large changes:
DefaultFileSource
constructor now takes aScheduler
AssetFileSource
does not use its own thread anymore; instead it uses the shared worker threadsGiven that our file requests need a way to "cancel" them (i.e. have the callback not invoked, I introduced
AssetFileSource::Impl::Request
, which holds ashared_ptr
to the callback. If that object gets destroyed, theweak_ptr
we're passing to the worker thread will be empty, and back on the main thread, the callback obviously can't be fired anymore. I'm not sure if using this violates @jfirebaugh's plea about not usingstd::shared_ptr
with actors (since technically, you could try to lock theweak_ptr
in the worker.I also added a
MGLThreadPool
object for Darwin, but implemented a global singleton for Android . I believe we should go the global singleton instance for Darwin as well (and removeMGLThreadPool
again), since Darwin never deallocates theDefaultFileSource
as part of the regular application workflow anyway (it's a singleton inMGLOfflineStorage
).