{"id":22796628,"url":"https://github.com/macmade/atomickit","last_synced_at":"2025-06-17T22:35:29.219Z","repository":{"id":49384444,"uuid":"95135506","full_name":"macmade/AtomicKit","owner":"macmade","description":"Concurrency made simple in Swift.","archived":false,"fork":false,"pushed_at":"2023-02-24T10:02:35.000Z","size":1718,"stargazers_count":94,"open_issues_count":2,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-19T17:13:06.276Z","etag":null,"topics":["atomic","atomicity","concurrency","lock","mutex","property","semaphore","swift","thread","thread-safety"],"latest_commit_sha":null,"homepage":"http://www.xs-labs.com","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/macmade.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":"macmade"}},"created_at":"2017-06-22T16:30:42.000Z","updated_at":"2025-01-25T14:24:19.000Z","dependencies_parsed_at":"2025-04-19T13:16:04.930Z","dependency_job_id":"3158b69a-cdc9-4736-830d-2f5727843059","html_url":"https://github.com/macmade/AtomicKit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/macmade/AtomicKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FAtomicKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FAtomicKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FAtomicKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FAtomicKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macmade","download_url":"https://codeload.github.com/macmade/AtomicKit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FAtomicKit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260451211,"owners_count":23011223,"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":["atomic","atomicity","concurrency","lock","mutex","property","semaphore","swift","thread","thread-safety"],"created_at":"2024-12-12T05:13:47.534Z","updated_at":"2025-06-17T22:35:24.209Z","avatar_url":"https://github.com/macmade.png","language":"Swift","funding_links":["https://github.com/sponsors/macmade"],"categories":[],"sub_categories":[],"readme":"AtomicKit\n=========\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/AtomicKit/ci-mac.yaml?label=macOS\u0026logo=apple)](https://github.com/macmade/AtomicKit/actions/workflows/ci-mac.yaml)\n[![Issues](http://img.shields.io/github/issues/macmade/AtomicKit.svg?logo=github)](https://github.com/macmade/AtomicKit/issues)\n![Status](https://img.shields.io/badge/status-active-brightgreen.svg?logo=git)\n![License](https://img.shields.io/badge/license-mit-brightgreen.svg?logo=open-source-initiative)  \n[![Contact](https://img.shields.io/badge/follow-@macmade-blue.svg?logo=twitter\u0026style=social)](https://twitter.com/macmade)\n[![Sponsor](https://img.shields.io/badge/sponsor-macmade-pink.svg?logo=github-sponsors\u0026style=social)](https://github.com/sponsors/macmade)\n\nAbout\n-----\n\n**Concurrency made simple in Swift.**\n\n**AtomicKit** is a Swift framework designed to ease dealing with concurrency in Swift projects.\n\n### Background\n\nComing from Objective-C and C++, I lacked a few features in Swift, like Objective-C's  `@atomic` or C++'s  `std::atomic`.\n\nApple's GCD (Grand Central Dispatch) is absolutely awesome when it comes to synchronization, but you'll have to use it explicitely in Swift.  \nWriting atomic/dispatched getters and setters is not a big deal, but it currently leads to a lot of boilerplate code, which I like to avoid in my projects.\n\nThe **AtomicKit** project intends to simplify this, by adding easy-to-use synchronization Swift types.\n\nDocumentation\n-------------\n\nDocumentation and API reference can be found at: http://doc.xs-labs.com/AtomicKit/\n\nSynchronization Primitives\n--------------------------\n\n**AtomicKit** exposes a few synchronization primitive types, like:\n\n - **Mutex**\n - **RecursiveMutex**\n - **UnfairLock**\n\nThese types conforms to the `AtomicKit.Lockable` protocol, which extends `NSLocking`, meaning they all have the following methods:\n\n```swift\npublic func lock()\npublic func unlock()\npublic func tryLock() -\u003e Bool\n```\n\n### AtomicKit.Mutex\n\nThis is a wrapper for `pthread_mutex_t`.  \nThis version is **not recursive**.\n\n### AtomicKit.RecursiveMutex\n\nThis is a wrapper for `pthread_mutex_t`.  \nThis version is **recursive**.\n\n### AtomicKit.UnfairLock\n\nThis is a wrapper for `os_unfair_lock_t`.\n\nSemaphores\n----------\n\n**AtomicKit** provides a `Semaphore` class.  \nSemaphores are initialized with a count, and may be named, in which case they are shared between multiple processes.\n\nThe `Semaphore` class exposes the following methods:\n\n```swift\npublic init( count: Int32 = 1, name: String? = nil )\npublic func wait()\npublic func signal()\npublic func tryWait() -\u003e Bool\n```\n\nInternally, the `Semaphore` class uses `POSIX` semaphores for named semaphores, and `MACH` semaphores for unnamed semaphores.\n\nRead-Write Locks\n----------------\n\n**AtomicKit** supports read-write locking mechanism using the `RWLock` class:\n\n```swift\npublic enum Intent\n{\n    case reading\n    case writing\n}\n\npublic func lock( for intent: Intent )\npublic func unlock()\npublic func tryLock( for intent: Intent ) -\u003e Bool\n```\n\nAtomic Properties\n------------------------\n\n**AtomicKit** provides a generic type called `Atomic`.  \nIf you're familiar with C++, you can think of it as `std::atomic`.\n\nThe goal is to provide a thread-safe property type that you can use in your own classes:\n\n```swift\nclass Foo\n{\n    public var bar = Atomic\u003c Bool \u003e( value: false )\n}\n```\n\nThe example above declares an atomic `Boolean` property.  \n\nIts value can be get with:\n\n```swift\nself.bar.get()\n```\n\nAnd can be set with:\n\n```swift\nself.bar.set( true )\n```\n\nInternally, `Atomic` uses an `UnfairLock`.\n\nIf more complex stuff is required with the value it holds, the `Atomic` generic type lets you execute a custom closure.\n\n```swift\nlet foo = Atomic\u003c String \u003e( value: \"hello\" )\n\nfoo.execute{ ( value: String ) in value.append( \", world\" ) }\n```\n\nYou can also use a return value from the closure:\n\n```swift\nlet isEmpty = foo.execute{ ( value: String ) -\u003e Bool in value.isEmpty }\n```\n\nAtomicity is guaranteed in both cases.\n\n### LockingValue\n\nUnder the hood, the `Atomic` class inherits from `LockingValue`.  \n`LockingValue` works just the same, but takes an extra generic parameter specifying the type of lock used for synchronization.\n\nAs mentioned above, `Atomic` uses an `UnfairLock`.  \nUsing `LockingValue`, you can specify another type of locking mechanism, as long as it conforms to the `NSLocking` protocol:\n\n```swift\nlet foo = LockingValue\u003c String?, NSRecursiveLock \u003e( value: nil )\n```\n\nDispatched Atomic Properties\n----------------------------\n\nUsing a locking mechanism is a way to achieve synchronization.  \nBut using **dispatch queues** also ensure synchronization between multiple concurrent accesses.\n\n**AtomicKit** supports this through the `DispatchedValue` generic class.\n\nA `DispatchedValue` is initialized with a default value, and with a dispatch queue:\n\n```swift\nlet foo = DispatchedValue\u003c String \u003e( value: \"\", queue: DispatchQueue.main )\n```\n\nThen, every call to the `get` or `set` methods will be executed on the provided queue, thus achieving effective synchronization.\n\nAs the `Atomic` type, `DispatchedValue` also lets you execute custom closures, that will be executed on the provided queue:\n\n```swift\nlet foo = DispatchedValue\u003c String \u003e( value: \"hello\", queue: DispatchQueue.main )\n\nfoo.execute{ ( value: String ) in value.append( \", world\" ) }\n\nlet isEmpty = foo.execute{ ( value: String ) -\u003e Bool in value.isEmpty }\n```\n\n### Dispatched properties and KVO\n\nAs it's a Swift generic type, the `DispatchedValue` class cannot be used from Objective-C, and so can't be used with KVO (key-value observing).\n\nThis might be a problem, especially if your project relies on Cocoa bindings, which use KVO.\n\n**AtomicKit** solves this by exposing Objective-C and KVO compatible versions of `DispatchedValue`, specialized for common Objective-C types:\n\n - **DispatchedArrayController**\n - **DispatchedBool**\n - **DispatchedMutableArray**\n - **DispatchedMutableDictionary**\n - **DispatchedMutableSet**\n - **DispatchedNumber**\n - **DispatchedObject**\n - **DispatchedString**\n - **DispatchedTree**\n\nAll of these types defaults to the main dispatch queue, if none is provided.  \nThis is especially handy when using Cocoa bindings, as changes often needs to occur on the main thread, for UI reasons.\n\nAll of these specializations expose a `value` property, which is observable using KVO.  \nIt also means you can safely use Cocoa bindings with them.\n\nLicense\n-------\n\n**AtomicKit** is released under the terms of the MIT license.\n\nRepository Infos\n----------------\n\n    Owner:          Jean-David Gadina - XS-Labs\n    Web:            www.xs-labs.com\n    Blog:           www.noxeos.com\n    Twitter:        @macmade\n    GitHub:         github.com/macmade\n    LinkedIn:       ch.linkedin.com/in/macmade/\n    StackOverflow:  stackoverflow.com/users/182676/macmade\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacmade%2Fatomickit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacmade%2Fatomickit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacmade%2Fatomickit/lists"}