[vlc-commits] [Git][videolan/vlc][master] 2 commits: macosx: Only notify of caches having been dropped after the cache writes are complete
François Cartegnie (@fcartegnie)
gitlab at videolan.org
Fri Sep 25 07:58:07 UTC 2026
François Cartegnie pushed to branch master at VideoLAN / VLC
Commits:
f000d09a by Claudio Cambra at 2026-09-25T09:48:51+02:00
macosx: Only notify of caches having been dropped after the cache writes are complete
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
9e59d4b3 by Claudio Cambra at 2026-09-25T09:48:51+02:00
macosx: Only notify cache changes after writes are actually complete
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
1 changed file:
- modules/gui/macosx/library/VLCLibraryModel.m
Changes:
=====================================
modules/gui/macosx/library/VLCLibraryModel.m
=====================================
@@ -147,6 +147,8 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
- (void)handleGenreUpdateEvent:(const vlc_ml_event_t * const)p_event;
- (void)handleGroupUpdateEvent:(const vlc_ml_event_t * const)p_event;
- (void)handlePlaylistUpdateEvent:(const vlc_ml_event_t * const)p_event;
+- (void)performAfterCacheWritesOnQueue:(dispatch_queue_t)queue
+ block:(dispatch_block_t)block;
@end
@@ -482,6 +484,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
return result;
}
+- (void)performAfterCacheWritesOnQueue:(dispatch_queue_t)queue
+ block:(dispatch_block_t)block
+{
+ // The sentinel runs after all cache writes already queued on this queue.
+ dispatch_barrier_async(queue, ^{
+ dispatch_async(dispatch_get_main_queue(), block);
+ });
+}
+
- (void)resetCachedListOfAudioMedia
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
@@ -494,8 +505,10 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_media_list_release(p_media_list);
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedAudioMedia = mediaArray;
- [self.changeDelegate notifyChange:VLCLibraryModelAudioMediaListReset withObject:self];
- [self resetCachedListOfMediaTitles];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelAudioMediaListReset withObject:self];
+ [self resetCachedListOfMediaTitles];
+ }];
});
});
}
@@ -544,7 +557,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedArtists = mutableArtistArray.copy;
self->_artistDict = mutableArtistDict.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelArtistListReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_artistCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelArtistListReset withObject:self];
+ }];
});
});
}
@@ -590,7 +605,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedAlbums = mutableAlbumArray.copy;
self->_albumDict = mutableAlbumDict.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelAlbumListReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_albumCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelAlbumListReset withObject:self];
+ }];
});
});
}
@@ -636,7 +653,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedGenres = mutableGenreArray.copy;
self->_genreDict = mutableGenreDict.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelGenreListReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_genreCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelGenreListReset withObject:self];
+ }];
});
});
}
@@ -681,8 +700,10 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_media_list_release(p_media_list);
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedVideoMedia = [mutableArray copy];
- [self.changeDelegate notifyChange:VLCLibraryModelVideoMediaListReset withObject:self];
- [self resetCachedListOfMediaTitles];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelVideoMediaListReset withObject:self];
+ [self resetCachedListOfMediaTitles];
+ }];
});
});
}
@@ -721,7 +742,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSArray<NSString *> * const sortedTitles = [titleSet.allObjects sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
dispatch_barrier_async(self->_mediaTitlesCacheModificationQueue, ^{
- self.cachedMediaTitles = sortedTitles;
+ self->_cachedMediaTitles = [sortedTitles copy];
});
});
}
@@ -776,7 +797,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
withCountLimit:_recentMediaLimit
withCompletion:^(NSArray * const mediaArray) {
self.cachedRecentMedia = mediaArray;
- [self.changeDelegate notifyChange:VLCLibraryModelRecentsMediaListReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelRecentsMediaListReset withObject:self];
+ }];
}];
}
@@ -810,7 +833,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
withCountLimit:_recentAudioMediaLimit
withCompletion:^(NSArray * const mediaArray) {
self.cachedRecentAudioMedia = mediaArray;
- [self.changeDelegate notifyChange:VLCLibraryModelRecentAudioMediaListReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelRecentAudioMediaListReset withObject:self];
+ }];
}];
}
@@ -854,7 +879,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_show_list_release(p_show_list);
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedListOfShows = mutableArray.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelListOfShowsReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelListOfShowsReset withObject:self];
+ }];
});
});
}
@@ -881,8 +908,10 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_media_list_release(p_movie_list);
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedListOfMovies = mutableArray.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelListOfMoviesReset withObject:self];
- [NSNotificationCenter.defaultCenter postNotificationName:VLCLibraryModelListOfMoviesReset object:self];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelListOfMoviesReset withObject:self];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCLibraryModelListOfMoviesReset object:self];
+ }];
});
});
}
@@ -971,7 +1000,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
vlc_ml_group_list_release(p_group_list);
dispatch_async(dispatch_get_main_queue(), ^{
self.cachedListOfGroups = mutableArray.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelListOfGroupsReset withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_groupCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelListOfGroupsReset withObject:self];
+ }];
});
});
}
@@ -1064,7 +1095,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
self.cachedListOfMonitoredFolders = mutableArray.copy;
self.folderObservers = mutableObservers.copy;
- [self.changeDelegate notifyChange:VLCLibraryModelListOfMonitoredFoldersUpdated withObject:self];
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
+ [self.changeDelegate notifyChange:VLCLibraryModelListOfMonitoredFoldersUpdated withObject:self];
+ }];
});
});
}
@@ -1162,20 +1195,44 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
- (void)dropCaches
{
- self.cachedVideoMedia = nil;
- self.cachedAudioMedia = nil;
- self.cachedRecentMedia = nil;
- self.cachedRecentAudioMedia = nil;
- self.cachedListOfShows = nil;
- self.cachedListOfMovies = nil;
- self.cachedListOfMonitoredFolders = nil;
- self.cachedAlbums = nil;
- self.cachedArtists = nil;
- self.cachedGenres = nil;
- self.cachedListOfGroups = nil;
- self.cachedMediaTitles = nil;
+ dispatch_queue_t const cacheQueues[] = {
+ _mediaItemCacheModificationQueue,
+ _albumCacheModificationQueue,
+ _artistCacheModificationQueue,
+ _genreCacheModificationQueue,
+ _groupCacheModificationQueue,
+ _mediaTitlesCacheModificationQueue,
+ };
+ const NSUInteger cacheQueueCount = sizeof(cacheQueues) / sizeof(cacheQueues[0]);
+ dispatch_group_t const cacheDropGroup = dispatch_group_create();
+
+ for (NSUInteger index = 0; index < cacheQueueCount; index++) {
+ dispatch_group_enter(cacheDropGroup);
+ }
- [self.changeDelegate notifyChange:VLCLibraryModelAllCachesDropped withObject:self];
+ self.cachedVideoMedia = nil;
+ self.cachedAudioMedia = nil;
+ self.cachedRecentMedia = nil;
+ self.cachedRecentAudioMedia = nil;
+ self.cachedListOfShows = nil;
+ self.cachedListOfMovies = nil;
+ self.cachedListOfMonitoredFolders = nil;
+ self.cachedAlbums = nil;
+ self.cachedArtists = nil;
+ self.cachedGenres = nil;
+ self.cachedListOfGroups = nil;
+ self.cachedMediaTitles = nil;
+
+ // Barrier sentinels complete after the setter writes on each queue.
+ for (NSUInteger index = 0; index < cacheQueueCount; index++) {
+ dispatch_barrier_async(cacheQueues[index], ^{
+ dispatch_group_leave(cacheDropGroup);
+ });
+ }
+
+ dispatch_group_notify(cacheDropGroup, dispatch_get_main_queue(), ^{
+ [self.changeDelegate notifyChange:VLCLibraryModelAllCachesDropped withObject:self];
+ });
}
- (void)performActionOnMediaItemInCache:(const int64_t)libraryId
@@ -1286,7 +1343,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
[recentMediaArray replaceObjectAtIndex:recentMediaIndex withObject:mediaItem];
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self.changeDelegate notifyChange:VLCLibraryModelRecentsMediaItemUpdated
@@ -1300,7 +1357,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
break;
}
- });
+ }];
}
if (showsArray != nil && showIndex != NSNotFound) {
@@ -1308,12 +1365,12 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
VLCMediaLibraryShow * const staleShow = showsArray[showIndex];
VLCMediaLibraryShow * const updatedShow = [VLCMediaLibraryShow showWithLibraryId:staleShow.libraryID];
[showsArray replaceObjectAtIndex:showIndex withObject:updatedShow];
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
[self.changeDelegate notifyChange:VLCLibraryModelShowUpdated withObject:updatedShow];
- });
+ }];
}
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self.changeDelegate notifyChange:VLCLibraryModelVideoMediaItemUpdated
@@ -1327,7 +1384,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSLog(@"Unknown type of media type encountered, don't know what to do in update");
break;
}
- });
+ }];
}];
}
@@ -1358,7 +1415,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
if (recentMediaArray != nil && recentMediaIndex != NSNotFound) {
[recentMediaArray removeObjectAtIndex:recentMediaIndex];
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self.changeDelegate notifyChange:VLCLibraryModelRecentsMediaItemDeleted
@@ -1372,7 +1429,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
break;
}
- });
+ }];
}
if (showsArray != nil && showIndex != NSNotFound) {
@@ -1382,20 +1439,20 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
[VLCMediaLibraryShow showWithLibraryId:staleShow.libraryID];
if (updatedShow == nil || updatedShow.episodeCount == 0) {
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
[self.changeDelegate notifyChange:VLCLibraryModelShowDeleted
withObject:@(staleShow.libraryID)];
- });
+ }];
} else {
[showsArray replaceObjectAtIndex:showIndex withObject:updatedShow];
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
[self.changeDelegate notifyChange:VLCLibraryModelShowUpdated
withObject:updatedShow];
- });
+ }];
}
}
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_mediaItemCacheModificationQueue block:^{
switch (mediaItem.mediaType) {
case VLC_ML_MEDIA_TYPE_VIDEO:
[self.changeDelegate notifyChange:VLCLibraryModelVideoMediaItemDeleted
@@ -1409,7 +1466,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
NSLog(@"Unknown type of media type encountered, don't know what to do in deletion");
break;
}
- });
+ }];
}];
}
@@ -1458,9 +1515,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
void (*cacheSetterFunction)(id, SEL, NSArray *) = (void *)cacheSetterImp;
cacheSetterFunction(self, setterSelector, mutableAudioGroupCache.copy);
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:queue block:^{
[self.changeDelegate notifyChange:notificationName withObject:audioGroupItem];
- });
+ }];
});
}
@@ -1499,9 +1556,9 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
void (*cacheSetterFunction)(id, SEL, NSArray *) = (void *)cacheSetterImp;
cacheSetterFunction(self, setterSelector, mutableAudioGroupCache.copy);
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:queue block:^{
[self.changeDelegate notifyChange:notificationName withObject:audioGroupItem];
- });
+ }];
});
}
@@ -1631,10 +1688,10 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
[mutableGroups removeObjectAtIndex:groupIdx];
self.cachedListOfGroups = mutableGroups.copy;
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_groupCacheModificationQueue block:^{
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelGroupDeleted
object:groupToDelete];
- });
+ }];
});
}
@@ -1672,10 +1729,10 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
[mutableGroups replaceObjectAtIndex:groupIdx withObject:group];
self.cachedListOfGroups = mutableGroups.copy;
- dispatch_async(dispatch_get_main_queue(), ^{
+ [self performAfterCacheWritesOnQueue:self->_groupCacheModificationQueue block:^{
[self->_defaultNotificationCenter postNotificationName:VLCLibraryModelGroupUpdated
object:group];
- });
+ }];
});
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c90941a0b9039aabe6e7442f6447ca34f7954c6d...9e59d4b38f804b33491b332df7643c1f80cc0b57
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/c90941a0b9039aabe6e7442f6447ca34f7954c6d...9e59d4b38f804b33491b332df7643c1f80cc0b57
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list