Toggle navigation
Toggle navigation
This project
Loading...
Sign in
ios
/
yh_sdwebimage
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Email Patches
Plain Diff
Browse Files
Authored by
DreamPiggy
7 years ago
Commit
1d82b12ba2c6e5885e28f8a59bc400524c13278c
1 parent
5946727d
Use a lock instead of barrier queue to avoid dispatch_sync blocking the main queue on race condition
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
62 additions
and
37 deletions
SDWebImage/SDWebImageDownloader.m
SDWebImage/SDWebImageDownloader.m
View file @
1d82b12
...
...
@@ -9,6 +9,10 @@
#import "SDWebImageDownloader.h"
#import "SDWebImageDownloaderOperation.h"
#define LOCK(...) dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); \
__VA_ARGS__; \
dispatch_semaphore_signal(self->_lock);
@interface
SDWebImageDownloadToken
()
@property
(
nonatomic
,
weak
,
nullable
)
NSOperation
<
SDWebImageDownloaderOperationInterface
>
*
downloadOperation
;
...
...
@@ -36,8 +40,7 @@
@property
(
assign
,
nonatomic
,
nullable
)
Class
operationClass
;
@property
(
strong
,
nonatomic
,
nonnull
)
NSMutableDictionary
<
NSURL
*
,
SDWebImageDownloaderOperation
*>
*
URLOperations
;
@property
(
strong
,
nonatomic
,
nullable
)
SDHTTPHeadersMutableDictionary
*
HTTPHeaders
;
// This queue is used to serialize the handling of the network responses of all the download operation in a single queue
@property
(
strong
,
nonatomic
,
nullable
)
dispatch_queue_t
barrierQueue
;
@property
(
strong
,
nonatomic
,
nonnull
)
dispatch_semaphore_t
lock
;
// a lock to keep the access to `URLOperations` thread-safe
// The session in which data tasks will run
@property
(
strong
,
nonatomic
)
NSURLSession
*
session
;
...
...
@@ -96,7 +99,7 @@
#else
_HTTPHeaders
=
[
@
{
@"Accept"
:
@"image/*;q=0.8"
}
mutableCopy
];
#endif
_
barrierQueue
=
dispatch_queue_create
(
"com.hackemist.SDWebImageDownloaderBarrierQueue"
,
DISPATCH_QUEUE_CONCURRENT
);
_
lock
=
dispatch_semaphore_create
(
1
);
_downloadTimeout
=
15
.
0
;
[
self
createNewSessionWithConfiguration
:
sessionConfiguration
];
...
...
@@ -231,13 +234,15 @@
}
-
(
void
)
cancel
:
(
nullable
SDWebImageDownloadToken
*
)
token
{
dispatch_barrier_async
(
self
.
barrierQueue
,
^
{
SDWebImageDownloaderOperation
*
operation
=
self
.
URLOperations
[
token
.
url
];
BOOL
canceled
=
[
operation
cancel
:
token
.
downloadOperationCancelToken
];
if
(
canceled
)
{
[
self
.
URLOperations
removeObjectForKey
:
token
.
url
];
}
});
NSURL
*
url
=
token
.
url
;
if
(
!
url
)
{
return
;
}
SDWebImageDownloaderOperation
*
operation
=
[
self
operationForURL
:
url
];
BOOL
canceled
=
[
operation
cancel
:
token
.
downloadOperationCancelToken
];
if
(
canceled
)
{
[
self
removeOperationForURL
:
url
];
}
}
-
(
nullable
SDWebImageDownloadToken
*
)
addProgressCallback
:
(
SDWebImageDownloaderProgressBlock
)
progressBlock
...
...
@@ -251,33 +256,24 @@
}
return
nil
;
}
__block
SDWebImageDownloadToken
*
token
=
nil
;
dispatch_barrier_sync
(
self
.
barrierQueue
,
^
{
SDWebImageDownloaderOperation
*
operation
=
self
.
URLOperations
[
url
];
if
(
!
operation
)
{
operation
=
createCallback
();
self
.
URLOperations
[
url
]
=
operation
;
__weak
SDWebImageDownloaderOperation
*
woperation
=
operation
;
operation
.
completionBlock
=
^
{
dispatch_barrier_sync
(
self
.
barrierQueue
,
^
{
SDWebImageDownloaderOperation
*
soperation
=
woperation
;
if
(
!
soperation
)
return
;
if
(
self
.
URLOperations
[
url
]
==
soperation
)
{
[
self
.
URLOperations
removeObjectForKey
:
url
];
};
});
};
}
id
downloadOperationCancelToken
=
[
operation
addHandlersForProgress
:
progressBlock
completed
:
completedBlock
];
token
=
[
SDWebImageDownloadToken
new
];
token
.
downloadOperation
=
operation
;
token
.
url
=
url
;
token
.
downloadOperationCancelToken
=
downloadOperationCancelToken
;
});
SDWebImageDownloaderOperation
*
operation
=
[
self
operationForURL
:
url
];
if
(
!
operation
)
{
operation
=
createCallback
();
[
self
setOperation
:
operation
forURL
:
url
];
__weak
typeof
(
self
)
wself
=
self
;
operation
.
completionBlock
=
^
{
__strong
typeof
(
wself
)
sself
=
wself
;
[
sself
removeOperationForURL
:
url
];
};
}
id
downloadOperationCancelToken
=
[
operation
addHandlersForProgress
:
progressBlock
completed
:
completedBlock
];
SDWebImageDownloadToken
*
token
=
[
SDWebImageDownloadToken
new
];
token
.
downloadOperation
=
operation
;
token
.
url
=
url
;
token
.
downloadOperationCancelToken
=
downloadOperationCancelToken
;
return
token
;
}
...
...
@@ -292,6 +288,35 @@
#pragma mark Helper methods
-
(
SDWebImageDownloaderOperation
*
)
operationForURL
:
(
NSURL
*
)
url
{
if
(
!
url
)
{
return
nil
;
}
SDWebImageDownloaderOperation
*
operation
;
LOCK
({
operation
=
[
self
.
URLOperations
objectForKey
:
url
];
});
return
operation
;
}
-
(
void
)
setOperation
:
(
SDWebImageDownloaderOperation
*
)
operation
forURL
:
(
NSURL
*
)
url
{
if
(
!
operation
||
!
url
)
{
return
;
}
LOCK
({
[
self
.
URLOperations
setObject
:
operation
forKey
:
url
];
});
}
-
(
void
)
removeOperationForURL
:
(
NSURL
*
)
url
{
if
(
!
url
)
{
return
;
}
LOCK
({
[
self
.
URLOperations
removeObjectForKey
:
url
];
});
}
-
(
SDWebImageDownloaderOperation
*
)
operationWithTask
:
(
NSURLSessionTask
*
)
task
{
SDWebImageDownloaderOperation
*
returnOperation
=
nil
;
for
(
SDWebImageDownloaderOperation
*
operation
in
self
.
downloadQueue
.
operations
)
{
...
...
Please
register
or
login
to post a comment