[vlc-commits] [Git][videolan/vlc][master] 3 commits: macosx: Perform concurrent reads, barriered writes in VLCLibraryModel

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Oct 13 19:36:17 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
d593dad2 by Claudio Cambra at 2025-10-13T19:03:33+00:00
macosx: Perform concurrent reads, barriered writes in VLCLibraryModel

This should speed up getting items from the VLCLibraryModel as we can now do concurrent reads

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
0e419701 by Claudio Cambra at 2025-10-13T19:03:33+00:00
macosx: Create convenience method to de-duplicate concurrent internal array access

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
629b2357 by Claudio Cambra at 2025-10-13T19:03:33+00:00
macosx: Remove unnecessary atomicity from VLCLibraryModel caches

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
=====================================
@@ -107,17 +107,17 @@ NSString * const VLCLibraryModelDiscoveryFailed = @"VLCLibraryModelDiscoveryFail
 
 @property (readwrite) NSArray<VLCMediaLibraryFolderObserver *> *folderObservers;
 
- at property (readwrite, atomic) NSArray *cachedAudioMedia;
- at property (readwrite, atomic) NSArray *cachedArtists;
- at property (readwrite, atomic) NSArray *cachedAlbums;
- at property (readwrite, atomic) NSArray *cachedGenres;
- at property (readwrite, atomic) NSArray *cachedVideoMedia;
- at property (readwrite, atomic) NSArray *cachedListOfShows;
- at property (readwrite, atomic) NSArray *cachedListOfMovies;
- at property (readwrite, atomic) NSArray *cachedListOfGroups;
- at property (readwrite, atomic) NSArray *cachedRecentMedia;
- at property (readwrite, atomic) NSArray *cachedRecentAudioMedia;
- at property (readwrite, atomic) NSArray *cachedListOfMonitoredFolders;
+ at property (readwrite, nonatomic) NSArray *cachedAudioMedia;
+ at property (readwrite, nonatomic) NSArray *cachedArtists;
+ at property (readwrite, nonatomic) NSArray *cachedAlbums;
+ at property (readwrite, nonatomic) NSArray *cachedGenres;
+ at property (readwrite, nonatomic) NSArray *cachedVideoMedia;
+ at property (readwrite, nonatomic) NSArray *cachedListOfShows;
+ at property (readwrite, nonatomic) NSArray *cachedListOfMovies;
+ at property (readwrite, nonatomic) NSArray *cachedListOfGroups;
+ at property (readwrite, nonatomic) NSArray *cachedRecentMedia;
+ at property (readwrite, nonatomic) NSArray *cachedRecentAudioMedia;
+ at property (readwrite, nonatomic) NSArray *cachedListOfMonitoredFolders;
 
 - (void)resetCachedListOfRecentMedia;
 - (void)resetCachedListOfRecentAudioMedia;
@@ -302,13 +302,13 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         _p_mediaLibrary = library;
         _p_eventCallback = vlc_ml_event_register_callback(_p_mediaLibrary, libraryCallback, (__bridge void *)self);
 
-        // Serial queues make avoiding concurrent modification of the caches easy, while avoiding
-        // locking other queues
-        _mediaItemCacheModificationQueue = dispatch_queue_create("mediaItemCacheModificationQueue", 0);
-        _albumCacheModificationQueue = dispatch_queue_create("albumCacheModificationQueue", 0);
-        _artistCacheModificationQueue = dispatch_queue_create("artistCacheModificationQueue", 0);
-        _genreCacheModificationQueue = dispatch_queue_create("genreCacheModificationQueue", 0);
-        _groupCacheModificationQueue = dispatch_queue_create("groupCacheModificationQueue", 0);
+        // Concurrent queues allow multiple readers while using barrier flags for exclusive writes,
+        // providing better performance than serial queues while maintaining thread safety
+        _mediaItemCacheModificationQueue = dispatch_queue_create("mediaItemCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
+        _albumCacheModificationQueue = dispatch_queue_create("albumCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
+        _artistCacheModificationQueue = dispatch_queue_create("artistCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
+        _genreCacheModificationQueue = dispatch_queue_create("genreCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
+        _groupCacheModificationQueue = dispatch_queue_create("groupCacheModificationQueue", DISPATCH_QUEUE_CONCURRENT);
 
         _defaultNotificationCenter = NSNotificationCenter.defaultCenter;
         [_defaultNotificationCenter addObserver:self
@@ -375,6 +375,15 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     return queryParams;
 }
 
+- (NSArray *)readCachedArray:(NSArray *)cachedArray fromQueue:(dispatch_queue_t)queue
+{
+    __block NSArray *result;
+    dispatch_sync(queue, ^{
+        result = cachedArray;
+    });
+    return result;
+}
+
 - (void)resetCachedListOfAudioMedia
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
@@ -397,7 +406,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedAudioMedia) {
         [self resetCachedListOfAudioMedia];
     }
-    return _cachedAudioMedia;
+    
+    return [self readCachedArray:_cachedAudioMedia fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (size_t)numberOfArtists
@@ -443,7 +453,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedArtists) {
         [self resetCachedListOfArtists];
     }
-    return _cachedArtists;
+    
+    return [self readCachedArray:_cachedArtists fromQueue:_artistCacheModificationQueue];
 }
 
 - (size_t)numberOfAlbums
@@ -486,7 +497,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedAlbums) {
         [self resetCachedListOfAlbums];
     }
-    return _cachedAlbums;
+    
+    return [self readCachedArray:_cachedAlbums fromQueue:_albumCacheModificationQueue];
 }
 
 - (size_t)numberOfGenres
@@ -529,7 +541,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedGenres) {
         [self resetCachedListOfGenres];
     }
-    return _cachedGenres;
+    
+    return [self readCachedArray:_cachedGenres fromQueue:_genreCacheModificationQueue];
 }
 
 - (size_t)numberOfVideoMedia
@@ -571,7 +584,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedVideoMedia) {
         [self resetCachedListOfVideoMedia];
     }
-    return _cachedVideoMedia;
+    
+    return [self readCachedArray:_cachedVideoMedia fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (void)getListOfRecentMediaOfType:(vlc_ml_media_type_t)type
@@ -623,7 +637,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedRecentMedia) {
         [self resetCachedListOfRecentMedia];
     }
-    return _cachedRecentMedia;
+    
+    return [self readCachedArray:_cachedRecentMedia fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (void)resetCachedListOfRecentAudioMedia
@@ -651,7 +666,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedRecentAudioMedia) {
         [self resetCachedListOfRecentAudioMedia];
     }
-    return _cachedRecentAudioMedia;
+    
+    return [self readCachedArray:_cachedRecentAudioMedia fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (void)resetCachedListOfShows
@@ -731,7 +747,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedListOfShows) {
         [self resetCachedListOfShows];
     }
-    return _cachedListOfShows;
+    
+    return [self readCachedArray:_cachedListOfShows fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (NSArray<VLCMediaLibraryMovie *> *)listOfMovies
@@ -739,7 +756,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedListOfMovies) {
         [self resetCachedListOfMovies];
     }
-    return _cachedListOfMovies;
+    
+    return [self readCachedArray:_cachedListOfMovies fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (size_t)numberOfGroups
@@ -757,7 +775,8 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     if (!_cachedListOfGroups) {
         [self resetCachedListOfGroups];
     }
-    return _cachedListOfGroups;
+    
+    return [self readCachedArray:_cachedListOfGroups fromQueue:_groupCacheModificationQueue];
 }
 
 - (void)resetCachedListOfGroups
@@ -875,7 +894,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         [self resetCachedListOfMonitoredFolders];
     }
 
-    return _cachedListOfMonitoredFolders;
+    return [self readCachedArray:_cachedListOfMonitoredFolders fromQueue:_mediaItemCacheModificationQueue];
 }
 
 - (nullable NSArray <VLCMediaLibraryAlbum *>*)listAlbumsOfParentType:(const enum vlc_ml_parent_type)parentType forID:(int64_t)ID;
@@ -978,7 +997,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
                                     const NSUInteger
                                  ))action
 {
-    dispatch_async(_mediaItemCacheModificationQueue, ^{
+    dispatch_barrier_async(_mediaItemCacheModificationQueue, ^{
         BOOL (^idCheckBlock)(VLCMediaLibraryMediaItem * const, const NSUInteger, BOOL * const) = ^BOOL(VLCMediaLibraryMediaItem * const mediaItem, const NSUInteger idx, BOOL * const stop) {
             NSAssert(mediaItem != nil, @"Cache list should not contain nil media items");
             return mediaItem.libraryID == libraryId;
@@ -1187,7 +1206,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
     NSParameterAssert([self respondsToSelector:setterSelector]);
     const int64_t itemId = audioGroupItem.libraryID;
 
-    dispatch_async(queue, ^{
+    dispatch_barrier_async(queue, ^{
         const NSUInteger audioGroupIndex = [self indexForAudioGroupInCache:cache
                                                                 withItemId:itemId];
         if (audioGroupIndex == NSNotFound) {
@@ -1218,7 +1237,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 {
     NSParameterAssert([self respondsToSelector:setterSelector]);
 
-    dispatch_async(queue, ^{
+    dispatch_barrier_async(queue, ^{
         const NSUInteger audioGroupIndex = [self indexForAudioGroupInCache:cache
                                                                 withItemId:itemId];
         if (audioGroupIndex == NSNotFound) {
@@ -1345,7 +1364,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
 
     const int64_t itemId = p_event->modification.i_entity_id;
 
-    dispatch_async(_groupCacheModificationQueue, ^{
+    dispatch_barrier_async(_groupCacheModificationQueue, ^{
         NSMutableArray * const mutableGroups = self.cachedListOfGroups.mutableCopy;
         const NSUInteger groupIdx =
             [mutableGroups indexOfObjectPassingTest:^BOOL(VLCMediaLibraryGroup * const group,
@@ -1380,7 +1399,7 @@ static void libraryCallback(void *p_data, const vlc_ml_event_t *p_event)
         return;
     }
 
-    dispatch_async(_groupCacheModificationQueue, ^{
+    dispatch_barrier_async(_groupCacheModificationQueue, ^{
         const NSUInteger groupIdx = 
             [self.cachedListOfGroups indexOfObjectPassingTest:^BOOL(VLCMediaLibraryGroup * const group,
                                                                     const NSUInteger idx,



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3789a6ba4abdefb8349f6608d3b190185bc22f98...629b235737467ddd2bddbabe2e88e7b6117023f4

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3789a6ba4abdefb8349f6608d3b190185bc22f98...629b235737467ddd2bddbabe2e88e7b6117023f4
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list