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
[bookmarks] Fix: collections reloading bug when BookmarkManager::LoadBookmarks()
is called multiple times.
#8133
base: master
Are you sure you want to change the base?
Conversation
When BookmarkManager::LoadBookmarks() is called multiple times, collections will be appended to the m_collections set on every call. ClearCategories() is moved to clean up the set right before reloading in the gui task. Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
da040c9
to
e61a89d
Compare
Honestly saying, I don't understand why |
Because filling the m_categories set with a new data is not synchronous and data dispatched several times between different threads before will be ready to use. And another problem is that MarkGroupID which is used as a key is incremented on every call, and will be different when we emplace the same collection multiple times and produce the data duplication. |
What happens when a user has a lot of bookmarks (and they're loaded slowly). OM is not running. Then the user imports a track from some app (not from Files, there's a bug that import from Files doesn't work on a cold start #4800 ), so there is a cold start of OM, and bookmarks are loaded asynchronously, and import of a file has started asynchronously? |
The key point is that both operations (the initial loading and an update) will be dispatched on the same GUI thread. 2024-05-11.10.48.28.mp4 |
Is the order guaranteed by code? E.g. bookmarks loading task will always fire first, and then track import task will be queued, right? |
Yes. The first bookmarks loading starts during the entire
- (void)initialize {
self.listeners = [NSHashTable<id<MWMLocationModeListener>> weakObjectsHashTable];
Framework &f = GetFramework();
// TODO: Review and improve this code.
f.SetPlacePageListeners([self]() { [self onMapObjectSelected]; },
[self](bool switchFullScreen) { [self onMapObjectDeselected:switchFullScreen]; },
[self]() { [self onMapObjectUpdated]; });
// TODO: Review and improve this code.
f.SetMyPositionModeListener([self](location::EMyPositionMode mode, bool routingActive) {
// TODO: Two global listeners are subscribed to the same event from the core.
// Probably it's better to subscribe only wnen needed and usubscribe in other cases.
// May be better solution would be multiobservers support in the C++ core.
[self processMyPositionStateModeEvent:location_helpers::mwmMyPositionMode(mode)];
});
self.userTouchesAction = UserTouchesActionNone;
[[MWMBookmarksManager sharedManager] addObserver:self];
[[MWMBookmarksManager sharedManager] loadBookmarks]; // <--- Here
[MWMFrameworkListener addObserver:self];
}
|
organicmaps/map/bookmark_manager.cpp Lines 1936 to 1940 in b4aecc4
organicmaps/map/bookmark_manager.cpp Lines 1895 to 1910 in b4aecc4
At this point, the Bookmarks screen is empty.
organicmaps/map/bookmark_manager.cpp Lines 1944 to 1946 in b4aecc4
organicmaps/map/bookmark_manager.cpp Lines 1946 to 1954 in b4aecc4
organicmaps/map/bookmark_manager.cpp Lines 2043 to 2071 in b4aecc4
After this point, the Bookmarks screen has reload bookmarks. There is obvious race condition between steps (2) and (5). This PR should fix this race condition by moving (1)-(2) into (5), i.e. calling |
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.
LoadBookmarks was not designed to be called more than once. The fact that it is called many times now, so bookmarks are loaded (and discarded) several times, doesn't feel right, not saying about the seemingly unnecessary overhead for large collections.
Let's investigate other side effects first, including Android, and think about alternative methods and solutions and their pros/cons.
So I'll try to write a separate method for reloading categories to avoid the reloading. |
LoadBookmarks() has reproducible race condition as described in #8133 (comment). This PR does resolve this issue and improves the code in general. The PR doesn't add any extra calls of LoadBookmarks(). Is there any reason why we shouldn't merge this PR? |
How do we proceed with this PR? If LoadBookmarks() is supposed to be called only once during the lifetime of the app, why does it have ClearCategories() in the beginning? I can see two options here:
@biodranik you are blocking a PR. Let's make a decision and move forward. |
I'd like to review this PR in context with files updating from the Cloud. What function do we call when some file was updated?
|
In the latest icloud implementation the Only the
|
When
BookmarkManager::LoadBookmarks()
is called multiple times, collections will be appended to them_categories
set on every call.BookmarkManager::LoadBookmarks()
can be called multiple times during the batch updates triggered by iCloud sync #7641.Bug result in ui:
Solution
ClearCategories() is moved to clean up the
m_categories
set before reloading in the gui task.Tested on: