{"id":19274409,"url":"https://github.com/regexident/sync","last_synced_at":"2025-09-29T06:31:51.272Z","repository":{"id":45865220,"uuid":"303725634","full_name":"regexident/Sync","owner":"regexident","description":"Useful synchronization primitives in Swift","archived":false,"fork":false,"pushed_at":"2023-04-17T16:35:40.000Z","size":64,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-10T18:11:38.770Z","etag":null,"topics":["multithreading","mutex","read-write-lock","rwlock","synchronization"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/regexident.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}},"created_at":"2020-10-13T14:13:52.000Z","updated_at":"2022-05-03T18:44:06.000Z","dependencies_parsed_at":"2025-01-10T18:11:16.823Z","dependency_job_id":"a2d74223-7dbe-4095-8a70-dbd7734dbf3d","html_url":"https://github.com/regexident/Sync","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regexident%2FSync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regexident%2FSync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regexident%2FSync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regexident%2FSync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/regexident","download_url":"https://codeload.github.com/regexident/Sync/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234597652,"owners_count":18857983,"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":["multithreading","mutex","read-write-lock","rwlock","synchronization"],"created_at":"2024-11-09T20:46:07.035Z","updated_at":"2025-09-29T06:31:46.011Z","avatar_url":"https://github.com/regexident.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sync\n\nUseful synchronization primitives in Swift.\n\n## `Mutex\u003cT\u003e`\n\nA fair mutual exclusion primitive useful for protecting shared data\n\n\u003e This mutex will block threads waiting for the lock to become available.\n\u003e The mutex can also be statically initialized or created via a new\n\u003e constructor. Each mutex has a type parameter which represents the data\n\u003e that it is protecting. The data can only be accessed through the `access`\n\u003e handle passed to the callback of `lock` and `tryLock`, which guarantees\n\u003e that the data is only ever accessed when the mutex is locked.\n\u003e\n\u003e Note: The implementation is based on `pthread_mutex_t` (64 bytes).\n\n### Minimal Example\n\n```swift\nlet mutex = try Mutex(0)\n\ntry! mutex.read { value in \n    print(value)\n}\n\ntry! mutex.write { access in\n    access { value in\n        value += 42\n    }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eReal-world Example\u003c/summary\u003e\n\n### Real-world Example\n\n```swift\nlet mutex = try Mutex(0)\n\nlet count: Int = 1000\n\nlet queue = DispatchQueue(\n    label: #function,\n    attributes: .concurrent\n)\n\nlet group = DispatchGroup()\n\nfor _ in 0..\u003ccount {\n    group.enter()\n\n    queue.async {\n        defer {\n            group.leave()\n        }\n        try! mutex.write { value in\n            value += 2\n        }\n    }\n}\n\ngroup.wait()\n\nlet value = try! mutex.unwrap()\n\nXCTAssertEqual(value, 2 * count)\n```\n\n\u003c/details\u003e\n\n## `UnfairMutex\u003cT\u003e`\n\nAn unfair mutual exclusion primitive useful for protecting shared data\n\n\u003e This mutex will block threads waiting for the lock to become available.\n\u003e The mutex can also be statically initialized or created via a new\n\u003e constructor. Each mutex has a type parameter which represents the data\n\u003e that it is protecting. The data can only be accessed through the `access`\n\u003e handle passed to the callback of `lock` and `tryLock`, which guarantees\n\u003e that the data is only ever accessed when the mutex is locked.\n\u003e\n\u003e Note: The implementation is based on `os_unfair_lock_s` (4 bytes).\n\n### Minimal Example\n\n```swift\nlet mutex = try Mutex(0)\n\ntry! mutex.read { value in \n    print(value)\n}\n\ntry! mutex.write { access in\n    access { value in\n        value += 42\n    }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eReal-world Example\u003c/summary\u003e\n\n### Real-world Example\n\n```swift\nlet unfairMutex = try UnfairMutex(0)\n\nlet count: Int = 1000\n\nlet queue = DispatchQueue(\n    label: #function,\n    attributes: .concurrent\n)\n\nlet group = DispatchGroup()\n\nfor _ in 0..\u003ccount {\n    group.enter()\n\n    queue.async {\n        defer {\n            group.leave()\n        }\n        try! unfairMutex.write { value in\n            value += 2\n        }\n    }\n}\n\ngroup.wait()\n\nlet value = try! unfairMutex.unwrap()\n\nXCTAssertEqual(value, 2 * count)\n```\n\n\u003c/details\u003e\n\n## `RWLock\u003cT\u003e`\n\nA reader-writer lock\n\n\u003e This type of lock allows a number of readers or at most one writer\n\u003e at any point in time. The write portion of this lock typically allows\n\u003e modification of the underlying data (exclusive access) and the read\n\u003e portion of this lock typically allows for read-only access (shared access).\n\u003e\n\u003e In comparison, a `Mutex` does not distinguish between readers or writers\n\u003e that acquire the lock, therefore blocking any threads waiting for the\n\u003e lock to become available. An `RWLock` will allow any number of readers\n\u003e to acquire the lock as long as a writer is not holding the lock.\n\u003e\n\u003e Note: The implementation is based on `pthread_rwlock_t` (200 bytes).\n\u003e \n\u003e **Important**: `RWLock` does not support priority inversion avoidance.\n\n### Minimal Example\n\n```swift\nlet rwlock = try RWLock(0)\n\ntry! rwlock.read { value in \n    print(value)\n}\n\ntry! rwlock.write { access in\n    access { value in\n        value += 42\n    }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eReal-world Example\u003c/summary\u003e\n\n### Real-world Example\n\n```swift\nlet rwlock = try RWLock(0)\n\nlet count: Int = 1000\n\nlet queue = DispatchQueue(\n    label: #function,\n    attributes: .concurrent\n)\n\nlet group = DispatchGroup()\n\nfor _ in 0..\u003ccount {\n    group.enter()\n\n    queue.async {\n        defer {\n            group.leave()\n        }\n        try! rwlock.write { value in\n            value += 2\n        }\n    }\n}\n\ngroup.wait()\n\nlet value = try! rwlock.unwrap()\n\nXCTAssertEqual(value, 2 * count)\n```\n\n\u003c/details\u003e\n\n## License\n\nThis project is licensed under the [**MPL-2.0**](https://www.tldrlegal.com/l/mpl-2.0) – see the [LICENSE.md](LICENSE.md) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregexident%2Fsync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fregexident%2Fsync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregexident%2Fsync/lists"}