From ad0705d126261b32d64c76bac4f831f8600d3d4d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 13 Nov 2015 18:30:12 -0800 Subject: [PATCH 1/4] Fix concurrent modification crash in app asset caching code --- .../ViewControllers/MainFrameViewController.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index f741e9a..21c4979 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -696,14 +696,14 @@ static NSMutableSet* hostList; _sortedAppList = [host.appList allObjects]; _sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)]; - // Start populating the box art cache asynchronously - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - Log(LOG_I, @"Starting per-computer box art caching job"); - for (App* app in host.appList) { + // Dispatch independent jobs to fetch each app art asset. This way we enumerate on the main thread + // which is safe for accessing the app list, and this also provides us the ability to use the sorted + // list to fetch items the user is more likely to view first. + for (App* app in _sortedAppList) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self updateBoxArtCacheForApp:app]; - } - Log(LOG_I, @"Per-computer box art caching job completed"); - }); + }); + } [hostScrollView removeFromSuperview]; [self.collectionView reloadData]; From e6aa16ad01db1b12d85131d492430c633a4387c3 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 13 Nov 2015 19:07:15 -0800 Subject: [PATCH 2/4] Revert "Fix concurrent modification crash in app asset caching code" This reverts commit ad0705d126261b32d64c76bac4f831f8600d3d4d. --- .../ViewControllers/MainFrameViewController.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 21c4979..f741e9a 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -696,14 +696,14 @@ static NSMutableSet* hostList; _sortedAppList = [host.appList allObjects]; _sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)]; - // Dispatch independent jobs to fetch each app art asset. This way we enumerate on the main thread - // which is safe for accessing the app list, and this also provides us the ability to use the sorted - // list to fetch items the user is more likely to view first. - for (App* app in _sortedAppList) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // Start populating the box art cache asynchronously + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + Log(LOG_I, @"Starting per-computer box art caching job"); + for (App* app in host.appList) { [self updateBoxArtCacheForApp:app]; - }); - } + } + Log(LOG_I, @"Per-computer box art caching job completed"); + }); [hostScrollView removeFromSuperview]; [self.collectionView reloadData]; From a8bcc6afba70241bd50b02a992126f41f86b406e Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 13 Nov 2015 19:52:35 -0800 Subject: [PATCH 3/4] Split the work into 2 jobs per computer to retrieve assets faster --- .../ViewControllers/MainFrameViewController.m | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index f741e9a..f259dde 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -696,13 +696,31 @@ static NSMutableSet* hostList; _sortedAppList = [host.appList allObjects]; _sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)]; - // Start populating the box art cache asynchronously + // Split the sorted array in half to allow 2 jobs to process app assets at once + NSArray *firstHalf; + NSArray *secondHalf; + NSRange range; + + range.location = 0; + range.length = [_sortedAppList count] / 2; + + firstHalf = [_sortedAppList subarrayWithRange:range]; + + range.location = range.length; + range.length = [_sortedAppList count] - range.length; + + secondHalf = [_sortedAppList subarrayWithRange:range]; + + // Start 2 jobs dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - Log(LOG_I, @"Starting per-computer box art caching job"); - for (App* app in host.appList) { + for (App* app in firstHalf) { + [self updateBoxArtCacheForApp:app]; + } + }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + for (App* app in secondHalf) { [self updateBoxArtCacheForApp:app]; } - Log(LOG_I, @"Per-computer box art caching job completed"); }); [hostScrollView removeFromSuperview]; From 5daa82b0ba47c8c887fa2adb1d68bf7201d083b3 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 13 Nov 2015 19:55:18 -0800 Subject: [PATCH 4/4] Show the hosts in alphabetical order rather than in an undefined order --- Limelight/Database/Host.h | 2 ++ Limelight/Database/Host.m | 4 ++++ Limelight/ViewControllers/MainFrameViewController.m | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Limelight/Database/Host.h b/Limelight/Database/Host.h index d866676..89968ac 100644 --- a/Limelight/Database/Host.h +++ b/Limelight/Database/Host.h @@ -18,6 +18,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) PairState pairState; @property (nonatomic) NSString * activeAddress; +- (NSComparisonResult)compareName:(Host *)other; + @end NS_ASSUME_NONNULL_END diff --git a/Limelight/Database/Host.m b/Limelight/Database/Host.m index 133f016..d115311 100644 --- a/Limelight/Database/Host.m +++ b/Limelight/Database/Host.m @@ -14,4 +14,8 @@ @synthesize online; @synthesize activeAddress; +- (NSComparisonResult)compareName:(Host *)other { + return [self.name caseInsensitiveCompare:other.name]; +} + @end diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index f259dde..3eb2cdc 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -640,7 +640,9 @@ static NSMutableSet* hostList; UIComputerView* compView; float prevEdge = -1; @synchronized (hostList) { - for (Host* comp in hostList) { + // Sort the host list in alphabetical order + NSArray* sortedHostList = [[hostList allObjects] sortedArrayUsingSelector:@selector(compareName:)]; + for (Host* comp in sortedHostList) { compView = [[UIComputerView alloc] initWithComputer:comp andCallback:self]; compView.center = CGPointMake([self getCompViewX:compView addComp:addComp prevEdge:prevEdge], hostScrollView.frame.size.height / 2); prevEdge = compView.frame.origin.x + compView.frame.size.width;