├── .gitignore
├── .travis.yml
├── Framework
├── Info.plist
└── YYDispatchQueuePool.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ └── contents.xcworkspacedata
│ └── xcshareddata
│ └── xcschemes
│ └── YYDispatchQueuePool.xcscheme
├── LICENSE
├── README.md
├── Snapshots
├── CTRunDraw.png
└── CTRunDrawLock.png
├── YYDispatchQueuePool.podspec
└── YYDispatchQueuePool
├── YYDispatchQueuePool.h
└── YYDispatchQueuePool.m
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | #
6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
7 |
8 | ## Build generated
9 | build/
10 | DerivedData/
11 |
12 | ## Various settings
13 | *.pbxuser
14 | !default.pbxuser
15 | *.mode1v3
16 | !default.mode1v3
17 | *.mode2v3
18 | !default.mode2v3
19 | *.perspectivev3
20 | !default.perspectivev3
21 | xcuserdata/
22 |
23 | ## Other
24 | *.moved-aside
25 | *.xccheckout
26 | *.xcuserstate
27 | *.xcscmblueprint
28 |
29 | ## Obj-C/Swift specific
30 | *.hmap
31 | *.ipa
32 | *.dSYM.zip
33 | *.dSYM
34 |
35 | # CocoaPods
36 | #
37 | # We recommend against adding the Pods directory to your .gitignore. However
38 | # you should judge for yourself, the pros and cons are mentioned at:
39 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
40 | #
41 | # Pods/
42 |
43 | # Carthage
44 | #
45 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
46 | # Carthage/Checkouts
47 |
48 | Carthage/Build
49 |
50 | # fastlane
51 | #
52 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
53 | # screenshots whenever they are needed.
54 | # For more information about the recommended setup visit:
55 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
56 |
57 | fastlane/report.xml
58 | fastlane/Preview.html
59 | fastlane/screenshots
60 | fastlane/test_output
61 |
62 | # Code Injection
63 | #
64 | # After new code Injection tools there's a generated folder /iOSInjectionProject
65 | # https://github.com/johnno1962/injectionforxcode
66 |
67 | iOSInjectionProject/
68 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode8
3 | xcode_project: Framework/YYDispatchQueuePool.xcodeproj
4 | xcode_scheme: YYDispatchQueuePool
5 |
6 | before_install:
7 | - env
8 | - xcodebuild -version
9 | - xcodebuild -showsdks
10 | - xcpretty --version
11 |
12 | script:
13 | - set -o pipefail
14 | - xcodebuild clean build -project "$TRAVIS_XCODE_PROJECT" -scheme "$TRAVIS_XCODE_SCHEME" | xcpretty
15 |
--------------------------------------------------------------------------------
/Framework/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Framework/YYDispatchQueuePool.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | D9A995131F0561E40062698B /* YYDispatchQueuePool.h in Headers */ = {isa = PBXBuildFile; fileRef = D9A995111F0561E40062698B /* YYDispatchQueuePool.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | D9A995141F0561E40062698B /* YYDispatchQueuePool.m in Sources */ = {isa = PBXBuildFile; fileRef = D9A995121F0561E40062698B /* YYDispatchQueuePool.m */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXFileReference section */
15 | D9A995051F0561A10062698B /* YYDispatchQueuePool.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YYDispatchQueuePool.framework; sourceTree = BUILT_PRODUCTS_DIR; };
16 | D9A995091F0561A10062698B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Framework/Info.plist; sourceTree = ""; };
17 | D9A995111F0561E40062698B /* YYDispatchQueuePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDispatchQueuePool.h; sourceTree = ""; };
18 | D9A995121F0561E40062698B /* YYDispatchQueuePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDispatchQueuePool.m; sourceTree = ""; };
19 | /* End PBXFileReference section */
20 |
21 | /* Begin PBXFrameworksBuildPhase section */
22 | D9A995011F0561A10062698B /* Frameworks */ = {
23 | isa = PBXFrameworksBuildPhase;
24 | buildActionMask = 2147483647;
25 | files = (
26 | );
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXFrameworksBuildPhase section */
30 |
31 | /* Begin PBXGroup section */
32 | D9A994FB1F0561A10062698B = {
33 | isa = PBXGroup;
34 | children = (
35 | D9A995101F0561E40062698B /* YYDispatchQueuePool */,
36 | D9A995061F0561A10062698B /* Products */,
37 | );
38 | sourceTree = "";
39 | };
40 | D9A995061F0561A10062698B /* Products */ = {
41 | isa = PBXGroup;
42 | children = (
43 | D9A995051F0561A10062698B /* YYDispatchQueuePool.framework */,
44 | );
45 | name = Products;
46 | sourceTree = "";
47 | };
48 | D9A995101F0561E40062698B /* YYDispatchQueuePool */ = {
49 | isa = PBXGroup;
50 | children = (
51 | D9A995111F0561E40062698B /* YYDispatchQueuePool.h */,
52 | D9A995121F0561E40062698B /* YYDispatchQueuePool.m */,
53 | D9A995091F0561A10062698B /* Info.plist */,
54 | );
55 | name = YYDispatchQueuePool;
56 | path = ../YYDispatchQueuePool;
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXHeadersBuildPhase section */
62 | D9A995021F0561A10062698B /* Headers */ = {
63 | isa = PBXHeadersBuildPhase;
64 | buildActionMask = 2147483647;
65 | files = (
66 | D9A995131F0561E40062698B /* YYDispatchQueuePool.h in Headers */,
67 | );
68 | runOnlyForDeploymentPostprocessing = 0;
69 | };
70 | /* End PBXHeadersBuildPhase section */
71 |
72 | /* Begin PBXNativeTarget section */
73 | D9A995041F0561A10062698B /* YYDispatchQueuePool */ = {
74 | isa = PBXNativeTarget;
75 | buildConfigurationList = D9A9950D1F0561A10062698B /* Build configuration list for PBXNativeTarget "YYDispatchQueuePool" */;
76 | buildPhases = (
77 | D9A995001F0561A10062698B /* Sources */,
78 | D9A995011F0561A10062698B /* Frameworks */,
79 | D9A995021F0561A10062698B /* Headers */,
80 | D9A995031F0561A10062698B /* Resources */,
81 | );
82 | buildRules = (
83 | );
84 | dependencies = (
85 | );
86 | name = YYDispatchQueuePool;
87 | productName = YYDispatchQueuePool;
88 | productReference = D9A995051F0561A10062698B /* YYDispatchQueuePool.framework */;
89 | productType = "com.apple.product-type.framework";
90 | };
91 | /* End PBXNativeTarget section */
92 |
93 | /* Begin PBXProject section */
94 | D9A994FC1F0561A10062698B /* Project object */ = {
95 | isa = PBXProject;
96 | attributes = {
97 | LastUpgradeCheck = 0900;
98 | ORGANIZATIONNAME = ibireme;
99 | TargetAttributes = {
100 | D9A995041F0561A10062698B = {
101 | CreatedOnToolsVersion = 9.0;
102 | };
103 | };
104 | };
105 | buildConfigurationList = D9A994FF1F0561A10062698B /* Build configuration list for PBXProject "YYDispatchQueuePool" */;
106 | compatibilityVersion = "Xcode 8.0";
107 | developmentRegion = en;
108 | hasScannedForEncodings = 0;
109 | knownRegions = (
110 | en,
111 | );
112 | mainGroup = D9A994FB1F0561A10062698B;
113 | productRefGroup = D9A995061F0561A10062698B /* Products */;
114 | projectDirPath = "";
115 | projectRoot = "";
116 | targets = (
117 | D9A995041F0561A10062698B /* YYDispatchQueuePool */,
118 | );
119 | };
120 | /* End PBXProject section */
121 |
122 | /* Begin PBXResourcesBuildPhase section */
123 | D9A995031F0561A10062698B /* Resources */ = {
124 | isa = PBXResourcesBuildPhase;
125 | buildActionMask = 2147483647;
126 | files = (
127 | );
128 | runOnlyForDeploymentPostprocessing = 0;
129 | };
130 | /* End PBXResourcesBuildPhase section */
131 |
132 | /* Begin PBXSourcesBuildPhase section */
133 | D9A995001F0561A10062698B /* Sources */ = {
134 | isa = PBXSourcesBuildPhase;
135 | buildActionMask = 2147483647;
136 | files = (
137 | D9A995141F0561E40062698B /* YYDispatchQueuePool.m in Sources */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | /* End PBXSourcesBuildPhase section */
142 |
143 | /* Begin XCBuildConfiguration section */
144 | D9A9950B1F0561A10062698B /* Debug */ = {
145 | isa = XCBuildConfiguration;
146 | buildSettings = {
147 | ALWAYS_SEARCH_USER_PATHS = NO;
148 | CLANG_ANALYZER_NONNULL = YES;
149 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
150 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
151 | CLANG_CXX_LIBRARY = "libc++";
152 | CLANG_ENABLE_MODULES = YES;
153 | CLANG_ENABLE_OBJC_ARC = YES;
154 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
155 | CLANG_WARN_BOOL_CONVERSION = YES;
156 | CLANG_WARN_COMMA = YES;
157 | CLANG_WARN_CONSTANT_CONVERSION = YES;
158 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
159 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
160 | CLANG_WARN_EMPTY_BODY = YES;
161 | CLANG_WARN_ENUM_CONVERSION = YES;
162 | CLANG_WARN_INFINITE_RECURSION = YES;
163 | CLANG_WARN_INT_CONVERSION = YES;
164 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
165 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
166 | CLANG_WARN_STRICT_PROTOTYPES = YES;
167 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
168 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
169 | CLANG_WARN_UNREACHABLE_CODE = YES;
170 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
171 | CODE_SIGN_IDENTITY = "iPhone Developer";
172 | COPY_PHASE_STRIP = NO;
173 | CURRENT_PROJECT_VERSION = 1;
174 | DEBUG_INFORMATION_FORMAT = dwarf;
175 | ENABLE_STRICT_OBJC_MSGSEND = YES;
176 | ENABLE_TESTABILITY = YES;
177 | GCC_C_LANGUAGE_STANDARD = gnu11;
178 | GCC_DYNAMIC_NO_PIC = NO;
179 | GCC_NO_COMMON_BLOCKS = YES;
180 | GCC_OPTIMIZATION_LEVEL = 0;
181 | GCC_PREPROCESSOR_DEFINITIONS = (
182 | "DEBUG=1",
183 | "$(inherited)",
184 | );
185 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
186 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
187 | GCC_WARN_UNDECLARED_SELECTOR = YES;
188 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
189 | GCC_WARN_UNUSED_FUNCTION = YES;
190 | GCC_WARN_UNUSED_VARIABLE = YES;
191 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
192 | MTL_ENABLE_DEBUG_INFO = YES;
193 | ONLY_ACTIVE_ARCH = YES;
194 | SDKROOT = iphoneos;
195 | VERSIONING_SYSTEM = "apple-generic";
196 | VERSION_INFO_PREFIX = "";
197 | };
198 | name = Debug;
199 | };
200 | D9A9950C1F0561A10062698B /* Release */ = {
201 | isa = XCBuildConfiguration;
202 | buildSettings = {
203 | ALWAYS_SEARCH_USER_PATHS = NO;
204 | CLANG_ANALYZER_NONNULL = YES;
205 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
207 | CLANG_CXX_LIBRARY = "libc++";
208 | CLANG_ENABLE_MODULES = YES;
209 | CLANG_ENABLE_OBJC_ARC = YES;
210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
211 | CLANG_WARN_BOOL_CONVERSION = YES;
212 | CLANG_WARN_COMMA = YES;
213 | CLANG_WARN_CONSTANT_CONVERSION = YES;
214 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
215 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
216 | CLANG_WARN_EMPTY_BODY = YES;
217 | CLANG_WARN_ENUM_CONVERSION = YES;
218 | CLANG_WARN_INFINITE_RECURSION = YES;
219 | CLANG_WARN_INT_CONVERSION = YES;
220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
221 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
222 | CLANG_WARN_STRICT_PROTOTYPES = YES;
223 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
224 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
225 | CLANG_WARN_UNREACHABLE_CODE = YES;
226 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
227 | CODE_SIGN_IDENTITY = "iPhone Developer";
228 | COPY_PHASE_STRIP = NO;
229 | CURRENT_PROJECT_VERSION = 1;
230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
231 | ENABLE_NS_ASSERTIONS = NO;
232 | ENABLE_STRICT_OBJC_MSGSEND = YES;
233 | GCC_C_LANGUAGE_STANDARD = gnu11;
234 | GCC_NO_COMMON_BLOCKS = YES;
235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
237 | GCC_WARN_UNDECLARED_SELECTOR = YES;
238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
239 | GCC_WARN_UNUSED_FUNCTION = YES;
240 | GCC_WARN_UNUSED_VARIABLE = YES;
241 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
242 | MTL_ENABLE_DEBUG_INFO = NO;
243 | SDKROOT = iphoneos;
244 | VALIDATE_PRODUCT = YES;
245 | VERSIONING_SYSTEM = "apple-generic";
246 | VERSION_INFO_PREFIX = "";
247 | };
248 | name = Release;
249 | };
250 | D9A9950E1F0561A10062698B /* Debug */ = {
251 | isa = XCBuildConfiguration;
252 | buildSettings = {
253 | APPLICATION_EXTENSION_API_ONLY = YES;
254 | CODE_SIGN_IDENTITY = "";
255 | DEFINES_MODULE = YES;
256 | DYLIB_COMPATIBILITY_VERSION = 1;
257 | DYLIB_CURRENT_VERSION = 1;
258 | DYLIB_INSTALL_NAME_BASE = "@rpath";
259 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
260 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
261 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
262 | PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYDispatchQueuePool;
263 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
264 | SKIP_INSTALL = YES;
265 | TARGETED_DEVICE_FAMILY = "1,2";
266 | };
267 | name = Debug;
268 | };
269 | D9A9950F1F0561A10062698B /* Release */ = {
270 | isa = XCBuildConfiguration;
271 | buildSettings = {
272 | APPLICATION_EXTENSION_API_ONLY = YES;
273 | CODE_SIGN_IDENTITY = "";
274 | DEFINES_MODULE = YES;
275 | DYLIB_COMPATIBILITY_VERSION = 1;
276 | DYLIB_CURRENT_VERSION = 1;
277 | DYLIB_INSTALL_NAME_BASE = "@rpath";
278 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
279 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
281 | PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYDispatchQueuePool;
282 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
283 | SKIP_INSTALL = YES;
284 | TARGETED_DEVICE_FAMILY = "1,2";
285 | };
286 | name = Release;
287 | };
288 | /* End XCBuildConfiguration section */
289 |
290 | /* Begin XCConfigurationList section */
291 | D9A994FF1F0561A10062698B /* Build configuration list for PBXProject "YYDispatchQueuePool" */ = {
292 | isa = XCConfigurationList;
293 | buildConfigurations = (
294 | D9A9950B1F0561A10062698B /* Debug */,
295 | D9A9950C1F0561A10062698B /* Release */,
296 | );
297 | defaultConfigurationIsVisible = 0;
298 | defaultConfigurationName = Release;
299 | };
300 | D9A9950D1F0561A10062698B /* Build configuration list for PBXNativeTarget "YYDispatchQueuePool" */ = {
301 | isa = XCConfigurationList;
302 | buildConfigurations = (
303 | D9A9950E1F0561A10062698B /* Debug */,
304 | D9A9950F1F0561A10062698B /* Release */,
305 | );
306 | defaultConfigurationIsVisible = 0;
307 | defaultConfigurationName = Release;
308 | };
309 | /* End XCConfigurationList section */
310 | };
311 | rootObject = D9A994FC1F0561A10062698B /* Project object */;
312 | }
313 |
--------------------------------------------------------------------------------
/Framework/YYDispatchQueuePool.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Framework/YYDispatchQueuePool.xcodeproj/xcshareddata/xcschemes/YYDispatchQueuePool.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
64 |
65 |
71 |
72 |
73 |
74 |
76 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 ibireme
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | YYDispatchQueuePool
2 | ==============
3 |
4 | [](https://raw.githubusercontent.com/ibireme/YYDispatchQueuePool/master/LICENSE)
5 | [](https://github.com/Carthage/Carthage)
6 | [](http://cocoapods.org/pods/YYDispatchQueuePool)
7 | [](http://cocoadocs.org/docsets/YYDispatchQueuePool)
8 | [](https://www.apple.com/nl/ios/)
9 | [](https://travis-ci.org/ibireme/YYDispatchQueuePool)
10 |
11 | iOS utility class to manage global dispatch queue.
12 | (It's a component of [YYKit](https://github.com/ibireme/YYKit))
13 |
14 | When use a concurrent queue to execute lots of blocks, I met this problem in some situation:
15 |
16 |
17 |
18 |
19 | When some block is locked, the concurrent queue may create lots of thread and may block the main thread.
20 | Use a global serial queue pool to avoid it.
21 |
22 | Usage
23 | ==============
24 | ```objc
25 | // Get a serial queue from global queue pool
26 | dispatch_queue_t queue = YYDispatchQueueGetForQOS(NSQualityOfServiceUtility);
27 |
28 | // Create a serial queue pool
29 | YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
30 | dispatch_queue_t queue = [pool queue];
31 | ```
32 |
33 | Installation
34 | ==============
35 |
36 | ### CocoaPods
37 |
38 | 1. Add `pod 'YYDispatchQueuePool'` to your Podfile.
39 | 2. Run `pod install` or `pod update`.
40 | 3. Import \.
41 |
42 |
43 | ### Carthage
44 |
45 | 1. Add `github "ibireme/YYDispatchQueuePool"` to your Cartfile.
46 | 2. Run `carthage update --platform ios` and add the framework to your project.
47 | 3. Import \.
48 |
49 |
50 | ### Manually
51 |
52 | 1. Download all the files in the YYDispatchQueuePool subdirectory.
53 | 2. Add the source files to your Xcode project.
54 | 3. Import `YYDispatchQueuePool.h`.
55 |
56 |
57 | Documentation
58 | ==============
59 | Full API documentation is available on [CocoaDocs](http://cocoadocs.org/docsets/YYDispatchQueuePool/).
60 | You can also install documentation locally using [appledoc](https://github.com/tomaz/appledoc).
61 |
62 |
63 | Requirements
64 | ==============
65 | This library requires `iOS 6.0+` and `Xcode 8.0+`.
66 |
67 |
68 | License
69 | ==============
70 | YYDispatchQueuePool is provided under the MIT license. See LICENSE file for details.
71 |
72 |
73 |
74 |
75 | ---
76 | 中文介绍
77 | ==============
78 | iOS 全局并发队列管理工具。
79 | (该项目是 [YYKit](https://github.com/ibireme/YYKit) 组件之一)
80 |
81 | 当用 concurrent queue 来执行大量 block 时,有时会遇到下面这种情况:
82 |
83 |
84 |
85 |
86 | 当某个 block 所在线程被锁住时,concurrent queue 会创建大量线程以至于占用了过多资源而影响到主线程。这里可以用一个全局的 serial queue pool 来尽量控制全局线程数。
87 |
88 | 用法
89 | ==============
90 | ```objc
91 | // 从全局的 queue pool 中获取一个 queue
92 | dispatch_queue_t queue = YYDispatchQueueGetForQOS(NSQualityOfServiceUtility);
93 |
94 | // 创建一个新的 serial queue pool
95 | YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
96 | dispatch_queue_t queue = [pool queue];
97 | ```
98 |
99 | 安装
100 | ==============
101 |
102 | ### CocoaPods
103 |
104 | 1. 在 Podfile 中添加 `pod 'YYDispatchQueuePool'`。
105 | 2. 执行 `pod install` 或 `pod update`。
106 | 3. 导入 \。
107 |
108 |
109 | ### Carthage
110 |
111 | 1. 在 Cartfile 中添加 `github "ibireme/YYDispatchQueuePool"`。
112 | 2. 执行 `carthage update --platform ios` 并将生成的 framework 添加到你的工程。
113 | 3. 导入 \。
114 |
115 |
116 | ### 手动安装
117 |
118 | 1. 下载 YYDispatchQueuePool 文件夹内的所有内容。
119 | 2. 将 YYDispatchQueuePool 内的源文件添加(拖放)到你的工程。
120 | 3. 导入 `YYDispatchQueuePool.h`。
121 |
122 |
123 | 文档
124 | ==============
125 | 你可以在 [CocoaDocs](http://cocoadocs.org/docsets/YYDispatchQueuePool/) 查看在线 API 文档,也可以用 [appledoc](https://github.com/tomaz/appledoc) 本地生成文档。
126 |
127 |
128 | 系统要求
129 | ==============
130 | 该项目最低支持 `iOS 6.0` 和 `Xcode 8.0`。
131 |
132 |
133 | 许可证
134 | ==============
135 | YYDispatchQueuePool 使用 MIT 许可证,详情见 LICENSE 文件。
136 |
137 |
138 | 相关文章
139 | ==============
140 | [iOS 保持界面流畅的技巧
141 | ](https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/)
142 |
143 |
--------------------------------------------------------------------------------
/Snapshots/CTRunDraw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ibireme/YYDispatchQueuePool/0ac83a856484b21f97aebf2d662caa1f1fa6fcd1/Snapshots/CTRunDraw.png
--------------------------------------------------------------------------------
/Snapshots/CTRunDrawLock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ibireme/YYDispatchQueuePool/0ac83a856484b21f97aebf2d662caa1f1fa6fcd1/Snapshots/CTRunDrawLock.png
--------------------------------------------------------------------------------
/YYDispatchQueuePool.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'YYDispatchQueuePool'
3 | s.summary = 'iOS utility class to manage global dispatch queue.'
4 | s.version = '1.0'
5 | s.license = { :type => 'MIT', :file => 'LICENSE' }
6 | s.authors = { 'ibireme' => 'ibireme@gmail.com' }
7 | s.social_media_url = 'http://blog.ibireme.com'
8 | s.homepage = 'https://github.com/ibireme/YYDispatchQueuePool'
9 | s.platform = :ios, '6.0'
10 | s.ios.deployment_target = '6.0'
11 | s.source = { :git => 'https://github.com/ibireme/YYDispatchQueuePool.git', :tag => s.version.to_s }
12 |
13 | s.requires_arc = true
14 | s.source_files = 'YYDispatchQueuePool/*.{h,m}'
15 | s.public_header_files = 'YYDispatchQueuePool/*.{h}'
16 |
17 | s.frameworks = 'UIKit'
18 |
19 | end
20 |
--------------------------------------------------------------------------------
/YYDispatchQueuePool/YYDispatchQueuePool.h:
--------------------------------------------------------------------------------
1 | //
2 | // YYDispatchQueueManager.h
3 | // YYKit
4 | //
5 | // Created by ibireme on 15/7/18.
6 | // Copyright (c) 2015 ibireme.
7 | //
8 | // This source code is licensed under the MIT-style license found in the
9 | // LICENSE file in the root directory of this source tree.
10 | //
11 |
12 | #import
13 |
14 | #if __has_include()
15 | FOUNDATION_EXPORT double YYDispatchQueuePoolVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char YYDispatchQueuePoolVersionString[];
17 | #endif
18 |
19 | #ifndef YYDispatchQueuePool_h
20 | #define YYDispatchQueuePool_h
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | /**
25 | A dispatch queue pool holds multiple serial queues.
26 | Use this class to control queue's thread count (instead of concurrent queue).
27 | */
28 | @interface YYDispatchQueuePool : NSObject
29 | - (instancetype)init UNAVAILABLE_ATTRIBUTE;
30 | + (instancetype)new UNAVAILABLE_ATTRIBUTE;
31 |
32 | /**
33 | Creates and returns a dispatch queue pool.
34 | @param name The name of the pool.
35 | @param queueCount Maxmium queue count, should in range (1, 32).
36 | @param qos Queue quality of service (QOS).
37 | @return A new pool, or nil if an error occurs.
38 | */
39 | - (instancetype)initWithName:(nullable NSString *)name queueCount:(NSUInteger)queueCount qos:(NSQualityOfService)qos;
40 |
41 | /// Pool's name.
42 | @property (nullable, nonatomic, readonly) NSString *name;
43 |
44 | /// Get a serial queue from pool.
45 | - (dispatch_queue_t)queue;
46 |
47 | + (instancetype)defaultPoolForQOS:(NSQualityOfService)qos;
48 |
49 | @end
50 |
51 | /// Get a serial queue from global queue pool with a specified qos.
52 | extern dispatch_queue_t YYDispatchQueueGetForQOS(NSQualityOfService qos);
53 |
54 | NS_ASSUME_NONNULL_END
55 |
56 | #endif
--------------------------------------------------------------------------------
/YYDispatchQueuePool/YYDispatchQueuePool.m:
--------------------------------------------------------------------------------
1 | //
2 | // YYDispatchQueueManager.m
3 | // YYKit
4 | //
5 | // Created by ibireme on 15/7/18.
6 | // Copyright (c) 2015 ibireme.
7 | //
8 | // This source code is licensed under the MIT-style license found in the
9 | // LICENSE file in the root directory of this source tree.
10 | //
11 |
12 | #import "YYDispatchQueuePool.h"
13 | #import
14 | #import
15 |
16 | #define MAX_QUEUE_COUNT 32
17 |
18 | static inline dispatch_queue_priority_t NSQualityOfServiceToDispatchPriority(NSQualityOfService qos) {
19 | switch (qos) {
20 | case NSQualityOfServiceUserInteractive: return DISPATCH_QUEUE_PRIORITY_HIGH;
21 | case NSQualityOfServiceUserInitiated: return DISPATCH_QUEUE_PRIORITY_HIGH;
22 | case NSQualityOfServiceUtility: return DISPATCH_QUEUE_PRIORITY_LOW;
23 | case NSQualityOfServiceBackground: return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
24 | case NSQualityOfServiceDefault: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
25 | default: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
26 | }
27 | }
28 |
29 | static inline qos_class_t NSQualityOfServiceToQOSClass(NSQualityOfService qos) {
30 | switch (qos) {
31 | case NSQualityOfServiceUserInteractive: return QOS_CLASS_USER_INTERACTIVE;
32 | case NSQualityOfServiceUserInitiated: return QOS_CLASS_USER_INITIATED;
33 | case NSQualityOfServiceUtility: return QOS_CLASS_UTILITY;
34 | case NSQualityOfServiceBackground: return QOS_CLASS_BACKGROUND;
35 | case NSQualityOfServiceDefault: return QOS_CLASS_DEFAULT;
36 | default: return QOS_CLASS_UNSPECIFIED;
37 | }
38 | }
39 |
40 | typedef struct {
41 | const char *name;
42 | void **queues;
43 | uint32_t queueCount;
44 | int32_t counter;
45 | } YYDispatchContext;
46 |
47 | static YYDispatchContext *YYDispatchContextCreate(const char *name,
48 | uint32_t queueCount,
49 | NSQualityOfService qos) {
50 | YYDispatchContext *context = calloc(1, sizeof(YYDispatchContext));
51 | if (!context) return NULL;
52 | context->queues = calloc(queueCount, sizeof(void *));
53 | if (!context->queues) {
54 | free(context);
55 | return NULL;
56 | }
57 | if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
58 | dispatch_qos_class_t qosClass = NSQualityOfServiceToQOSClass(qos);
59 | for (NSUInteger i = 0; i < queueCount; i++) {
60 | dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
61 | dispatch_queue_t queue = dispatch_queue_create(name, attr);
62 | context->queues[i] = (__bridge_retained void *)(queue);
63 | }
64 | } else {
65 | long identifier = NSQualityOfServiceToDispatchPriority(qos);
66 | for (NSUInteger i = 0; i < queueCount; i++) {
67 | dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
68 | dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));
69 | context->queues[i] = (__bridge_retained void *)(queue);
70 | }
71 | }
72 | context->queueCount = queueCount;
73 | if (name) {
74 | context->name = strdup(name);
75 | }
76 | return context;
77 | }
78 |
79 | static void YYDispatchContextRelease(YYDispatchContext *context) {
80 | if (!context) return;
81 | if (context->queues) {
82 | for (NSUInteger i = 0; i < context->queueCount; i++) {
83 | void *queuePointer = context->queues[i];
84 | dispatch_queue_t queue = (__bridge_transfer dispatch_queue_t)(queuePointer);
85 | const char *name = dispatch_queue_get_label(queue);
86 | if (name) strlen(name);
87 | queue = nil;
88 | }
89 | free(context->queues);
90 | context->queues = NULL;
91 | }
92 | if (context->name) free((void *)context->name);
93 | free(context);
94 | }
95 |
96 | static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) {
97 | uint32_t counter = (uint32_t)OSAtomicIncrement32(&context->counter);
98 | void *queue = context->queues[counter % context->queueCount];
99 | return (__bridge dispatch_queue_t)(queue);
100 | }
101 |
102 |
103 | static YYDispatchContext *YYDispatchContextGetForQOS(NSQualityOfService qos) {
104 | static YYDispatchContext *context[5] = {0};
105 | switch (qos) {
106 | case NSQualityOfServiceUserInteractive: {
107 | static dispatch_once_t onceToken;
108 | dispatch_once(&onceToken, ^{
109 | int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
110 | count = count < 1 ? 1 : count > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : count;
111 | context[0] = YYDispatchContextCreate("com.ibireme.yykit.user-interactive", count, qos);
112 | });
113 | return context[0];
114 | } break;
115 | case NSQualityOfServiceUserInitiated: {
116 | static dispatch_once_t onceToken;
117 | dispatch_once(&onceToken, ^{
118 | int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
119 | count = count < 1 ? 1 : count > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : count;
120 | context[1] = YYDispatchContextCreate("com.ibireme.yykit.user-initiated", count, qos);
121 | });
122 | return context[1];
123 | } break;
124 | case NSQualityOfServiceUtility: {
125 | static dispatch_once_t onceToken;
126 | dispatch_once(&onceToken, ^{
127 | int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
128 | count = count < 1 ? 1 : count > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : count;
129 | context[2] = YYDispatchContextCreate("com.ibireme.yykit.utility", count, qos);
130 | });
131 | return context[2];
132 | } break;
133 | case NSQualityOfServiceBackground: {
134 | static dispatch_once_t onceToken;
135 | dispatch_once(&onceToken, ^{
136 | int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
137 | count = count < 1 ? 1 : count > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : count;
138 | context[3] = YYDispatchContextCreate("com.ibireme.yykit.background", count, qos);
139 | });
140 | return context[3];
141 | } break;
142 | case NSQualityOfServiceDefault:
143 | default: {
144 | static dispatch_once_t onceToken;
145 | dispatch_once(&onceToken, ^{
146 | int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
147 | count = count < 1 ? 1 : count > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : count;
148 | context[4] = YYDispatchContextCreate("com.ibireme.yykit.default", count, qos);
149 | });
150 | return context[4];
151 | } break;
152 | }
153 | }
154 |
155 |
156 | @implementation YYDispatchQueuePool {
157 | @public
158 | YYDispatchContext *_context;
159 | }
160 |
161 | - (void)dealloc {
162 | if (_context) {
163 | YYDispatchContextRelease(_context);
164 | _context = NULL;
165 | }
166 | }
167 |
168 | - (instancetype)initWithContext:(YYDispatchContext *)context {
169 | self = [super init];
170 | if (!context) return nil;
171 | self->_context = context;
172 | _name = context->name ? [NSString stringWithUTF8String:context->name] : nil;
173 | return self;
174 | }
175 |
176 | - (instancetype)initWithName:(NSString *)name queueCount:(NSUInteger)queueCount qos:(NSQualityOfService)qos {
177 | if (queueCount == 0 || queueCount > MAX_QUEUE_COUNT) return nil;
178 | self = [super init];
179 | _context = YYDispatchContextCreate(name.UTF8String, (uint32_t)queueCount, qos);
180 | if (!_context) return nil;
181 | _name = name;
182 | return self;
183 | }
184 |
185 | - (dispatch_queue_t)queue {
186 | return YYDispatchContextGetQueue(_context);
187 | }
188 |
189 | + (instancetype)defaultPoolForQOS:(NSQualityOfService)qos {
190 | switch (qos) {
191 | case NSQualityOfServiceUserInteractive: {
192 | static YYDispatchQueuePool *pool;
193 | static dispatch_once_t onceToken;
194 | dispatch_once(&onceToken, ^{
195 | pool = [[YYDispatchQueuePool alloc] initWithContext:YYDispatchContextGetForQOS(qos)];
196 | });
197 | return pool;
198 | } break;
199 | case NSQualityOfServiceUserInitiated: {
200 | static YYDispatchQueuePool *pool;
201 | static dispatch_once_t onceToken;
202 | dispatch_once(&onceToken, ^{
203 | pool = [[YYDispatchQueuePool alloc] initWithContext:YYDispatchContextGetForQOS(qos)];
204 | });
205 | return pool;
206 | } break;
207 | case NSQualityOfServiceUtility: {
208 | static YYDispatchQueuePool *pool;
209 | static dispatch_once_t onceToken;
210 | dispatch_once(&onceToken, ^{
211 | pool = [[YYDispatchQueuePool alloc] initWithContext:YYDispatchContextGetForQOS(qos)];
212 | });
213 | return pool;
214 | } break;
215 | case NSQualityOfServiceBackground: {
216 | static YYDispatchQueuePool *pool;
217 | static dispatch_once_t onceToken;
218 | dispatch_once(&onceToken, ^{
219 | pool = [[YYDispatchQueuePool alloc] initWithContext:YYDispatchContextGetForQOS(qos)];
220 | });
221 | return pool;
222 | } break;
223 | case NSQualityOfServiceDefault:
224 | default: {
225 | static YYDispatchQueuePool *pool;
226 | static dispatch_once_t onceToken;
227 | dispatch_once(&onceToken, ^{
228 | pool = [[YYDispatchQueuePool alloc] initWithContext:YYDispatchContextGetForQOS(NSQualityOfServiceDefault)];
229 | });
230 | return pool;
231 | } break;
232 | }
233 | }
234 |
235 | @end
236 |
237 | dispatch_queue_t YYDispatchQueueGetForQOS(NSQualityOfService qos) {
238 | return YYDispatchContextGetQueue(YYDispatchContextGetForQOS(qos));
239 | }
240 |
--------------------------------------------------------------------------------