{"id":44254062,"url":"https://github.com/cascable/runloop-queue","last_synced_at":"2026-02-10T16:01:50.362Z","repository":{"id":157964752,"uuid":"81962672","full_name":"Cascable/runloop-queue","owner":"Cascable","description":"A GCD-like queue powered with the magic (and ruggedness) of CFRunLoop.","archived":false,"fork":false,"pushed_at":"2025-11-05T10:31:43.000Z","size":24,"stargazers_count":23,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-11-05T12:15:55.809Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cascable.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-02-14T16:00:22.000Z","updated_at":"2025-11-05T10:31:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"7d311a67-dc38-4f19-8988-47576db5431d","html_url":"https://github.com/Cascable/runloop-queue","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Cascable/runloop-queue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Frunloop-queue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Frunloop-queue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Frunloop-queue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Frunloop-queue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cascable","download_url":"https://codeload.github.com/Cascable/runloop-queue/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Frunloop-queue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29306431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T15:37:45.286Z","status":"ssl_error","status_checked_at":"2026-02-10T15:37:41.567Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-02-10T16:01:49.512Z","updated_at":"2026-02-10T16:01:50.346Z","avatar_url":"https://github.com/Cascable.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RunloopQueue\n\n`RunloopQueue` is a class for running code on a background thread. It works a *bit* like Grand Central Dispatch, but is instead powered by the magic of run loops! \n\n`RunloopQueue` works on both macOS and iOS.\n\n```swift\nqueue = RunloopQueue(named: \"My Cool Queue\")\n\nqueue.async {\n    // This code is running on a background thread.\n    performAReallyLongOperation()\n}\n```\n\n### Usage\n\nTo use `RunloopQueue`, copy the `RunloopQueue.swift` file to your project. You can also add `RunloopQueue+Streams.swift` and `RunloopQueue+URLConnection.swift` if you'd like the `Stream` and `URLConnection` helpers.\n\n### Real-World Applications\n\n`RunloopQueue` is currently being used in our Cascable family of apps, most notably in `CascableCore`, our SDK for working with WiFi-enabled cameras. `CascableCore` uses `RunloopQueue` for managing connections with the cameras it supports, and scheduling messages back and forth. You can find out more about `CascableCore` in our [CascableCore Demo App](https://github.com/Cascable/cascablecore-demo).\n\n### RunloopQueue vs. Grand Central Dispatch\n\n`RunloopQueue` is *not* designed to be a replacement for Grand Central Dispatch. In fact, if you're performing the common flow of starting on the main thread, performing some background work then calling back to the main thread at the end of the operation to update UI, you'll need Grand Central Dispatch to get back to the main thread.\n\n```swift\nqueue.async {\n    // This code is running on a background thread.\n    performAReallyLongOperation()\n    DispatchQueue.main.async {\n        // This code is running on the main thread.\n        performUIUpdates()\n    }\n}\n```\n\nHowever, `RunloopQueue` does offer some advantages over Grand Central Dispatch in certain circumstances:\n\n#### Thread Consistency\n\n`RunloopQueue` guarantees that all operations on a given `RunloopQueue` instance will be executed on the same thread, whether they're performed synchronously or asynchronously. This can be handy if you're interacting with a library that expects thread consistency.\n\n#### Support For \"Where Am I?\" Checking\n\n`RunloopQueue` provides the `isRunningOnQueue()` method for checking whether or not the code calling that method is running on the given `RunloopQueue` instance's thread. \n\n#### Safe(er) Synchronous Operations\n\nGrand Central Dispatch is *very* unsafe when it comes to synchronous operations, and it's very easy to deadlock your code. Personally, it's so unsafe that I ban its use in any project that I have that sort of influence over. \n\n`RunloopQueue`, however, is much better in this regard. Thanks to the `isRunningOnQueue()` method, it can avoid deadlocks when synchronous operations start other synchronous operations:\n\n```swift\nqueue.sync {\n    queue.sync {\n        print(\"Inner sync\")\n    }\n    print(\"Outer sync\")\n}\n```\n\nPlease note that as in *any* multithreaded environment, synchronous operations are prone to deadlocking if you're not careful. \n\n#### Friendly to Streams and URL Connections\n\nIf you're working with streams or `URLConnection` objects, `RunloopQueue` provides convenience methods for enqueuing such objects on its background thread. This is great if you'd like to process your incoming data in the background:\n\n```swift\nlet input: InputStream = …\nlet output: OutputStream = …\n\ninput.delegate = self\noutput.delegate = self\n\n// Scheduling the streams on a RunloopQueue will cause their \n// delegate methods to be called on a background thread.\nqueue.schedule(input)\nqueue.schedule(output)\n\ninput.open()\noutput.open()\n```\n\n### Objective-C\n\n`RunloopQueue` is written in Swift 3, but is fully compatible with Objective-C.\n\n```objc\nself.runloopQueue = [[CBLRunloopQueue alloc] initWithName:@\"My Cool Queue\"];\n[self.runloopQueue async:^{\n    [self performAReallyLongOperation];\n}];\n\n[self.runloopQueue scheduleStream:self.inputStream];\n```\n\n### License\n\nFor more information, see the [LICENSE.md](LICENSE.md) file.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcascable%2Frunloop-queue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcascable%2Frunloop-queue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcascable%2Frunloop-queue/lists"}