µFramework consisting of `NSOperationQueue` subclasses (Swift & Obj-C) which allow scheduling operations in serial subgroups inside a concurrent queue
Swift & Obj-C µFramework consisting of NSOperationQueue
subclasses which allow scheduling operations in serial subgroups inside concurrent queues.
In some scenarios, operations scheduled in an NSOperationQueue
depend on a subset of other operations and should be processed in order, but don’t depend on the remaining operations in the queue.
So far, this could be solved by:
With this µFramework, a single operation queue can be used to schedule all operations and obtain the best of both worlds.
Dependent operations are grouped into “subgroups” which are guaranteed to be processed in a serial fashion inside each subgroup, while operations from other subgroups are processed concurrently (while serial inside their own subgroup) and regular operations (i.e. without defined subgroup) are processed concurrently with all others. This is done by leveraging NSOperation
s dependencies and using an auxiliary data structure to store all subgroups’ operations.
@import APNSubGroupOperationQueue
let subGroupQueue = SubGroupOperationQueue<String>()
// schedule operations in subgroups "A", "B" and "C"
// these will run serially inside each subgroup, but concurrently with other subgroups' operations
subGroupQueue.addOperation(opA1, withKey: "A")
subGroupQueue.addOperation(opA2, withKey: "A")
subGroupQueue.addOperation(opA3, withKey: "A")
subGroupQueue.addOperations([opB1, opB2, opB3], withKey: "B")
subGroupQueue.addOperation({ /* opC1 */ }, withKey: "C")
subGroupQueue.addOperation({ /* opC2 */ }, withKey: "C")
subGroupQueue.addOperation({ /* opC3 */ }, withKey: "C")
// query current subgroup's operations (a snapshot)
let aOps = subGroupQueue["A"]
let bOps = subGroupQueue["B"]
let cOps = subGroupQueue.subGroupOperations(forKey: "C")
AnyHashable
)
@import APNSubGroupOperationQueue
let dynamicSubGroupQueue = SubGroupQueue<AnyHashable> // or simply a `DynamicSubGroupOperationQueue`
dynamicSubGroupQueue.addOperation(opX1, withKey: "X")
dynamicSubGroupQueue.addOperation(opX2, withKey: "X")
dynamicSubGroupQueue.addOperation(opX3, withKey: "X")
dynamicSubGroupQueue.addOperations([opN1, opN2, opN3], withKey: 1337)
let date = Date()
dynamicSubGroupQueue.addOperation({ /* opD1 */ }, withKey: date)
dynamicSubGroupQueue.addOperation({ /* opD2 */ }, withKey: date)
dynamicSubGroupQueue.addOperation({ /* opD3 */ }, withKey: date)
// query current subgroup's operations (a snapshot)
let xOps = subGroupQueue["X"]
let nOps = subGroupQueue[1337]
let dOps = subGroupQueue.subGroupOperations(forKey: date)
@import APNSubGroupOperationQueue;
APNSubGroupOperationQueue *subGroupQueue = [APNSubGroupOperationQueue new];
// schedule operations in subgroups "A", "B" and "C"
// these will run serially inside each subgroup, but concurrently with other subgroups' operations
[subGroupQueue addOperation:opA1 withKey:@"A"];
[subGroupQueue addOperation:opA2 withKey:@"A"];
[subGroupQueue addOperation:opA2 withKey:@"A"];
[subGroupQueue addOperations::@[opB1, opB2, opB3] withKey:@"B" waitUntilFinished:false];
[subGroupQueue addOperationWithBlock:^{ /* opC1 */ } andKey:@"C"];
[subGroupQueue addOperationWithBlock:^{ /* opC2 */ } andKey:@"C"];
[subGroupQueue addOperationWithBlock:^{ /* opC3 */ } andKey:@"C"];
// query current subgroup's operations (a snapshot)
NSArray<NSOperation*> *aOps = [subGroupQueue subGroupOperationsForKey:@"A"];
NSArray<NSOperation*> *bOps = [subGroupQueue subGroupOperationsForKey:@"B"];
NSArray<NSOperation*> *cOps = [subGroupQueue subGroupOperationsForKey:@"C"];
// Objective-C uses a `DynamicSubGroupOperationQueue` which allows a more flexible usage, since keys only need to be `NSObject`'s (`AnyHashable`)
[subGroupQueue addOperations:@[opN1, opN2, opN3] withKey:@1337 waitUntilFinished:false];
NSDate *date = [NSDate date];
[subGroupQueue addOperationWithBlock:^{ /* opD1 */ } andKey:date];
[subGroupQueue addOperationWithBlock:^{ /* opD2 */ } andKey:date];
4.x
(current)3.x
2.x
2.3.0
2.2.0
2.1.0
Add APNSubGroupOperationQueue to your Podfile
and run pod install
:
# CocoaPods
pod 'APNSubGroupOperationQueue', '~> 4.0'
Add APNSubGroupOperationQueue to your Cartfile
(package dependency) or Cartfile.private
(development dependency):
github "p4checo/APNSubGroupOperationQueue" ~> 4.0
Add APNSubGroupOperationQueue to your Package.swift
:
import PackageDescription
let package = Package(
name: "HelloWorld",
dependencies: [
.package(url: "https://github.com/p4checo/APNSubGroupOperationQueue.git", from: "4.0.0"),
]
)
See CONTRIBUTING.