From a255953d34d7ad81aa2d3cfde099f10523d5a712 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Mon, 26 Nov 2018 17:25:38 -0800 Subject: [PATCH] Avoid using global Mutex variables (#1252) After 5c9815f, some Mutexes are used as global C++ variables which are loaded before main(). Since the Mutex constructor checks for unfair lock experiment, it triggers an experiment configuration load, and our app isn't ready to respond that early in the process. --- Source/ASImageNode.mm | 8 ++++++-- Source/ASTextNode2.mm | 6 +++--- Source/Details/ASBasicImageDownloader.mm | 16 ++++++++++++---- Source/TextKit/ASTextKitContext.mm | 8 ++++++-- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Source/ASImageNode.mm b/Source/ASImageNode.mm index bed6655608..097320fd65 100644 --- a/Source/ASImageNode.mm +++ b/Source/ASImageNode.mm @@ -433,11 +433,15 @@ typedef void (^ASImageNodeDrawParametersBlock)(ASWeakMapEntry *entry); } static ASWeakMap *cache = nil; -// Allocate cacheLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) -static auto *cacheLock = new ASDN::Mutex; + (ASWeakMapEntry *)contentsForkey:(ASImageNodeContentsKey *)key drawParameters:(id)drawParameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled { + static dispatch_once_t onceToken; + static ASDN::Mutex *cacheLock = nil; + dispatch_once(&onceToken, ^{ + cacheLock = new ASDN::Mutex(); + }); + { ASDN::MutexLocker l(*cacheLock); if (!cache) { diff --git a/Source/ASTextNode2.mm b/Source/ASTextNode2.mm index a96f4f00f8..14c2afd93f 100644 --- a/Source/ASTextNode2.mm +++ b/Source/ASTextNode2.mm @@ -54,11 +54,11 @@ * NOTE: Be careful to copy `text` if needed. */ static NS_RETURNS_RETAINED ASTextLayout *ASTextNodeCompatibleLayoutWithContainerAndText(ASTextContainer *container, NSAttributedString *text) { - // Allocate layoutCacheLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) - static auto *layoutCacheLock = new ASDN::Mutex; - static NSCache *textLayoutCache; static dispatch_once_t onceToken; + static ASDN::Mutex *layoutCacheLock; + static NSCache *textLayoutCache; dispatch_once(&onceToken, ^{ + layoutCacheLock = new ASDN::Mutex(); textLayoutCache = [[NSCache alloc] init]; }); diff --git a/Source/Details/ASBasicImageDownloader.mm b/Source/Details/ASBasicImageDownloader.mm index c13fc728bc..c5c1f72b68 100644 --- a/Source/Details/ASBasicImageDownloader.mm +++ b/Source/Details/ASBasicImageDownloader.mm @@ -38,12 +38,20 @@ NSString * const kASBasicImageDownloaderContextCompletionBlock = @"kASBasicImage @implementation ASBasicImageDownloaderContext static NSMutableDictionary *currentRequests = nil; -// Allocate currentRequestsLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) -static auto *currentRequestsLock = new ASDN::Mutex; + ++ (ASDN::Mutex *)currentRequestLock +{ + static dispatch_once_t onceToken; + static ASDN::Mutex *currentRequestsLock; + dispatch_once(&onceToken, ^{ + currentRequestsLock = new ASDN::Mutex(); + }); + return currentRequestsLock; +} + (ASBasicImageDownloaderContext *)contextForURL:(NSURL *)URL { - ASDN::MutexLocker l(*currentRequestsLock); + ASDN::MutexLocker l(*self.currentRequestLock); if (!currentRequests) { currentRequests = [[NSMutableDictionary alloc] init]; } @@ -57,7 +65,7 @@ static auto *currentRequestsLock = new ASDN::Mutex; + (void)cancelContextWithURL:(NSURL *)URL { - ASDN::MutexLocker l(*currentRequestsLock); + ASDN::MutexLocker l(*self.currentRequestLock); if (currentRequests) { [currentRequests removeObjectForKey:URL]; } diff --git a/Source/TextKit/ASTextKitContext.mm b/Source/TextKit/ASTextKitContext.mm index d7f6d7b0be..75582f471f 100644 --- a/Source/TextKit/ASTextKitContext.mm +++ b/Source/TextKit/ASTextKitContext.mm @@ -34,9 +34,13 @@ { if (self = [super init]) { + static dispatch_once_t onceToken; + static ASDN::Mutex *mutex; + dispatch_once(&onceToken, ^{ + mutex = new ASDN::Mutex(); + }); + // Concurrently initialising TextKit components crashes (rdar://18448377) so we use a global lock. - // Allocate mutex on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) - static auto *mutex = new ASDN::Mutex; ASDN::MutexLocker l(*mutex); __instanceLock__ = std::make_shared();