{"id":18433422,"url":"https://github.com/p4checo/apnsubgroupoperationqueue","last_synced_at":"2025-04-07T19:31:26.955Z","repository":{"id":56900922,"uuid":"55862672","full_name":"p4checo/APNSubGroupOperationQueue","owner":"p4checo","description":"µFramework consisting of `NSOperationQueue` subclasses (Swift \u0026 Obj-C) which allow scheduling operations in serial subgroups inside a concurrent queue","archived":false,"fork":false,"pushed_at":"2019-04-29T01:29:12.000Z","size":70,"stargazers_count":15,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-03-14T16:23:06.009Z","etag":null,"topics":["concurrency","micro-framework","nsoperationqueue","objective-c","operationqueue","serial","subgroups","swift"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p4checo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-09T19:19:36.000Z","updated_at":"2022-04-12T09:35:22.000Z","dependencies_parsed_at":"2022-08-21T02:50:49.971Z","dependency_job_id":null,"html_url":"https://github.com/p4checo/APNSubGroupOperationQueue","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4checo%2FAPNSubGroupOperationQueue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4checo%2FAPNSubGroupOperationQueue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4checo%2FAPNSubGroupOperationQueue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4checo%2FAPNSubGroupOperationQueue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p4checo","download_url":"https://codeload.github.com/p4checo/APNSubGroupOperationQueue/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247716257,"owners_count":20984208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","micro-framework","nsoperationqueue","objective-c","operationqueue","serial","subgroups","swift"],"created_at":"2024-11-06T05:34:29.752Z","updated_at":"2025-04-07T19:31:26.659Z","avatar_url":"https://github.com/p4checo.png","language":"Swift","readme":"# APNSubGroupOperationQueue\n[![license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/p4checo/APNSubGroupOperationQueue/master/LICENSE)\n[![release](https://img.shields.io/github/release/p4checo/APNSubGroupOperationQueue.svg)](https://github.com/p4checo/APNSubGroupOperationQueue/releases)\n![platforms](https://img.shields.io/badge/platform-iOS%20%7C%20OS%20X%20%7C%20tvOS%20%7C%20watchOS-lightgrey.svg)\n[![Build Status](https://travis-ci.org/p4checo/APNSubGroupOperationQueue.svg?branch=master)](https://travis-ci.org/p4checo/APNSubGroupOperationQueue)\n[![codecov.io](https://codecov.io/github/p4checo/APNSubGroupOperationQueue/coverage.svg?branch=master)](https://codecov.io/github/p4checo/APNSubGroupOperationQueue?branch=master)\n[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/APNSubGroupOperationQueue.svg)](http://cocoadocs.org/docsets/APNSubGroupOperationQueue)\n[![Carthage](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![CocoaPods](https://img.shields.io/cocoapods/v/APNSubGroupOperationQueue.svg)](https://cocoapods.org/)\n[![Swift 4.2](https://img.shields.io/badge/Swift-4.2-orange.svg?style=flat)](https://developer.apple.com/swift/)\n\nSwift \u0026 Obj-C µFramework consisting of `NSOperationQueue` subclasses which allow scheduling operations in serial subgroups inside concurrent queues.\n\nIn 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.\n\nSo far, this could be solved by:\n  - using separate queues for each subset of dependent operations (can become unmanageable, wasteful)\n  - defining the queue as serial (sub-optimal performance)\n\nWith this µFramework, a single operation queue can be used to schedule all operations and obtain the best of both worlds.\n\nDependent 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.\n\n## Use\n\n### Swift\n\n#### Single SubGroup Key type \n```swift\n@import APNSubGroupOperationQueue\n\nlet subGroupQueue = SubGroupOperationQueue\u003cString\u003e()\n\n// schedule operations in subgroups \"A\", \"B\" and \"C\"\n// these will run serially inside each subgroup, but concurrently with other subgroups' operations\n\nsubGroupQueue.addOperation(opA1, withKey: \"A\")\nsubGroupQueue.addOperation(opA2, withKey: \"A\")\nsubGroupQueue.addOperation(opA3, withKey: \"A\")\n\nsubGroupQueue.addOperations([opB1, opB2, opB3], withKey: \"B\")\n\nsubGroupQueue.addOperation({ /* opC1 */ }, withKey: \"C\")\nsubGroupQueue.addOperation({ /* opC2 */ }, withKey: \"C\")\nsubGroupQueue.addOperation({ /* opC3 */ }, withKey: \"C\")\n\n// query current subgroup's operations (a snapshot)\nlet aOps = subGroupQueue[\"A\"]\nlet bOps = subGroupQueue[\"B\"]\nlet cOps = subGroupQueue.subGroupOperations(forKey: \"C\")\n```\n\n#### Multiple SubGroup Key types (via `AnyHashable`)\n```swift\n@import APNSubGroupOperationQueue\n\nlet dynamicSubGroupQueue = SubGroupQueue\u003cAnyHashable\u003e // or simply a `DynamicSubGroupOperationQueue`\n\ndynamicSubGroupQueue.addOperation(opX1, withKey: \"X\")\ndynamicSubGroupQueue.addOperation(opX2, withKey: \"X\")\ndynamicSubGroupQueue.addOperation(opX3, withKey: \"X\")\n\ndynamicSubGroupQueue.addOperations([opN1, opN2, opN3], withKey: 1337)\n\nlet date = Date()\ndynamicSubGroupQueue.addOperation({ /* opD1 */ }, withKey: date)\ndynamicSubGroupQueue.addOperation({ /* opD2 */ }, withKey: date)\ndynamicSubGroupQueue.addOperation({ /* opD3 */ }, withKey: date)\n\n// query current subgroup's operations (a snapshot)\nlet xOps = subGroupQueue[\"X\"]\nlet nOps = subGroupQueue[1337]\nlet dOps = subGroupQueue.subGroupOperations(forKey: date)\n```\n\n### Objective-C\n```objc\n@import APNSubGroupOperationQueue;\n\nAPNSubGroupOperationQueue *subGroupQueue = [APNSubGroupOperationQueue new];\n\n// schedule operations in subgroups \"A\", \"B\" and \"C\"\n// these will run serially inside each subgroup, but concurrently with other subgroups' operations\n[subGroupQueue addOperation:opA1 withKey:@\"A\"];\n[subGroupQueue addOperation:opA2 withKey:@\"A\"];\n[subGroupQueue addOperation:opA2 withKey:@\"A\"];\n\n[subGroupQueue addOperations::@[opB1, opB2, opB3] withKey:@\"B\" waitUntilFinished:false];\n\n[subGroupQueue addOperationWithBlock:^{ /* opC1 */ } andKey:@\"C\"];\n[subGroupQueue addOperationWithBlock:^{ /* opC2 */ } andKey:@\"C\"];\n[subGroupQueue addOperationWithBlock:^{ /* opC3 */ } andKey:@\"C\"];\n\n// query current subgroup's operations (a snapshot)\nNSArray\u003cNSOperation*\u003e *aOps = [subGroupQueue subGroupOperationsForKey:@\"A\"];\nNSArray\u003cNSOperation*\u003e *bOps = [subGroupQueue subGroupOperationsForKey:@\"B\"];\nNSArray\u003cNSOperation*\u003e *cOps = [subGroupQueue subGroupOperationsForKey:@\"C\"];\n\n// Objective-C uses a `DynamicSubGroupOperationQueue` which allows a more flexible usage, since keys only need to be `NSObject`'s (`AnyHashable`)\n[subGroupQueue addOperations:@[opN1, opN2, opN3] withKey:@1337 waitUntilFinished:false];\n\nNSDate *date = [NSDate date];\n[subGroupQueue addOperationWithBlock:^{ /* opD1 */ } andKey:date];\n[subGroupQueue addOperationWithBlock:^{ /* opD2 */ } andKey:date];\n```\n## Compatibility\n\n### `4.x` (current)\n\n- iOS 10.0+, macOS 10.12, tvOS 10.0+, watchOS 3.0+  \n- Xcode 10.2+\n- Swift 5.0\n\n### `3.x`\n\n- iOS 10.0+, macOS 10.12, tvOS 10.0+, watchOS 3.0+  \n- Xcode 10\n- Swift 4.2\n\n### `2.x`\n\n- iOS 8.0+, macOS 10.9+, tvOS 9.0+, watchOS 2.0+\n- `2.3.0`\n  + Xcode 9.4\n  + Swift 4.1\n- `2.2.0`\n  + Xcode 9\n  + Swift 4.0\n- `2.1.0`\n  + Xcode 8\n  + Swift 3\n\n\n## Integration\n\n### CocoaPods\nAdd APNSubGroupOperationQueue to your `Podfile` and run `pod install`:\n\n```ruby\n# CocoaPods\npod 'APNSubGroupOperationQueue', '~\u003e 4.0'\n```\n\n### Carthage\n\nAdd APNSubGroupOperationQueue to your `Cartfile` (package dependency) or `Cartfile.private`\n(development dependency):\n\n```\ngithub \"p4checo/APNSubGroupOperationQueue\" ~\u003e 4.0\n```\n\n### Swift Package Manager\n\nAdd APNSubGroupOperationQueue to your `Package.swift`:\n\n```swift\nimport PackageDescription\n\nlet package = Package(\n  name: \"HelloWorld\",\n  dependencies: [\n    .package(url: \"https://github.com/p4checo/APNSubGroupOperationQueue.git\", from: \"4.0.0\"),\n  ]\n)\n```\n\n### git Submodule\n\n1. Add this repository as a submodule.\n2. Drag APNSubGroupOperationQueue.xcodeproj into your project or workspace.\n3. Link your target against APNSubGroupOperationQueue.framework of your platform.\n4. If linking againts an Application target, ensure the framework gets copied into the bundle. If linking against a Framework target, the application linking to it should also include APNSubGroupOperationQueue.\n\n## Contributing\n\nSee [CONTRIBUTING](https://github.com/p4checo/APNSubGroupOperationQueue/blob/master/CONTRIBUTING.md).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4checo%2Fapnsubgroupoperationqueue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp4checo%2Fapnsubgroupoperationqueue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4checo%2Fapnsubgroupoperationqueue/lists"}