@@ -158,7 +158,7 @@ - (NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request
158
158
}
159
159
160
160
// Save the session into memory.
161
- [self setSessionInFetcherMap: self forSessionID: _sessionID];
161
+ [[ self class ] setSessionInFetcherMap: self forSessionID: _sessionID];
162
162
163
163
_request = [request copy ];
164
164
@@ -200,7 +200,7 @@ - (NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request
200
200
}
201
201
202
202
// Save the session into memory.
203
- [self setSessionInFetcherMap: self forSessionID: _sessionID];
203
+ [[ self class ] setSessionInFetcherMap: self forSessionID: _sessionID];
204
204
205
205
_request = [request copy ];
206
206
@@ -291,7 +291,7 @@ - (void)URLSession:(NSURLSession *)session
291
291
// Explicitly remove the session so it won't be reused. The weak map table should
292
292
// remove the session on deallocation, but dealloc may not happen immediately after
293
293
// calling `finishTasksAndInvalidate`.
294
- [self setSessionInFetcherMap: nil forSessionID: sessionID];
294
+ [[ self class ] setSessionInFetcherMap: nil forSessionID: sessionID];
295
295
}
296
296
}
297
297
@@ -540,18 +540,19 @@ - (void)removeTempItemAtURL:(NSURL *)fileURL {
540
540
541
541
// / Gets the fetcher with the session ID.
542
542
+ (instancetype )fetcherWithSessionIdentifier : (NSString *)sessionIdentifier {
543
- NSMapTable <NSString *, GULNetworkURLSession *> *sessionIdentifierToFetcherMap =
544
- [self sessionIDToFetcherMap ];
545
- GULNetworkURLSession *session = [sessionIdentifierToFetcherMap objectForKey: sessionIdentifier];
543
+ GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID: sessionIdentifier];
546
544
if (!session && [sessionIdentifier hasPrefix: kGULNetworkBackgroundSessionConfigIDPrefix ]) {
547
545
session = [[GULNetworkURLSession alloc ] initWithNetworkLoggerDelegate: nil ];
548
546
[session setSessionID: sessionIdentifier];
549
- [sessionIdentifierToFetcherMap setObject : session forKey : sessionIdentifier];
547
+ [self setSessionInFetcherMap : session forSessionID : sessionIdentifier];
550
548
}
551
549
return session;
552
550
}
553
551
554
552
// / Returns a map of the fetcher by session ID. Creates a map if it is not created.
553
+ // / When reading and writing from/to the session map, don't use this method directly.
554
+ // / To avoid thread safety issues, use one of the helper methods at the bottom of the
555
+ // / file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID:
555
556
+ (NSMapTable <NSString *, GULNetworkURLSession *> *)sessionIDToFetcherMap {
556
557
static NSMapTable *sessionIDToFetcherMap;
557
558
@@ -562,6 +563,16 @@ + (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier {
562
563
return sessionIDToFetcherMap;
563
564
}
564
565
566
+ + (NSLock *)sessionIDToFetcherMapReadWriteLock {
567
+ static NSLock *lock;
568
+
569
+ static dispatch_once_t onceToken;
570
+ dispatch_once (&onceToken, ^{
571
+ lock = [[NSLock alloc ] init ];
572
+ });
573
+ return lock;
574
+ }
575
+
565
576
// / Returns a map of system provided completion handler by session ID. Creates a map if it is not
566
577
// / created.
567
578
+ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary {
@@ -661,26 +672,32 @@ - (void)URLSession:(NSURLSession *)session
661
672
662
673
#pragma mark - Helper Methods
663
674
664
- - (void )setSessionInFetcherMap : (GULNetworkURLSession *)session forSessionID : (NSString *)sessionID {
665
- GULNetworkURLSession *existingSession = [self sessionFromFetcherMapForSessionID: sessionID];
675
+ + (void )setSessionInFetcherMap : (GULNetworkURLSession *)session forSessionID : (NSString *)sessionID {
676
+ [[self sessionIDToFetcherMapReadWriteLock ] lock ];
677
+ GULNetworkURLSession *existingSession =
678
+ [[[self class ] sessionIDToFetcherMap ] objectForKey: sessionID];
666
679
if (existingSession) {
667
680
// Invalidating doesn't seem like the right thing to do here since it may cancel an active
668
681
// background transfer if the background session is handling multiple requests. The old
669
682
// session will be dropped from the map table, but still complete its request.
670
683
NSString *message = [NSString stringWithFormat: @" Discarding session: %@ " , existingSession];
671
- [_loggerDelegate GULNetwork_logWithLevel: kGULNetworkLogLevelInfo
672
- messageCode: kGULNetworkMessageCodeURLSession019
673
- message: message];
684
+ [existingSession-> _loggerDelegate GULNetwork_logWithLevel: kGULNetworkLogLevelInfo
685
+ messageCode: kGULNetworkMessageCodeURLSession019
686
+ message: message];
674
687
}
675
688
if (session) {
676
689
[[[self class ] sessionIDToFetcherMap ] setObject: session forKey: sessionID];
677
690
} else {
678
691
[[[self class ] sessionIDToFetcherMap ] removeObjectForKey: sessionID];
679
692
}
693
+ [[self sessionIDToFetcherMapReadWriteLock ] unlock ];
680
694
}
681
695
682
- - (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID : (NSString *)sessionID {
683
- return [[[self class ] sessionIDToFetcherMap ] objectForKey: sessionID];
696
+ + (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID : (NSString *)sessionID {
697
+ [[self sessionIDToFetcherMapReadWriteLock ] lock ];
698
+ GULNetworkURLSession *session = [[[self class ] sessionIDToFetcherMap ] objectForKey: sessionID];
699
+ [[self sessionIDToFetcherMapReadWriteLock ] unlock ];
700
+ return session;
684
701
}
685
702
686
703
- (void )callCompletionHandler : (GULNetworkURLSessionCompletionHandler)handler
0 commit comments