Thread synchronization made easy.

Related tags

GCD SwiftSafe
Overview

SwiftSafe

Thread synchronization made easy.

Why?

Performance-sensitive classes need internal state synchronization, so that external accessors don't break the internal invariants and cause race conditions. Using GCD (Grand Central Dispatch) directly can confuse newcomers, because the API doesn't necessarily reflect the actual reason why it's being used. That's why wrapping it in a straighforward Swifty API can introduce a bit more clarity to your code. See examples below.

Concurrency modes supported

  • EREW - Exclusive Read, Exclusive Write: The most common synchronization method, where only one thread can read or write your protected resource at one time. One big disadvantage is that it's prone to deadlocks.
  • CREW - Concurrent Read, Exclusive Write: Less common, but IMO more powerful method, where multiple threads can read, but only one thread can write at one time. Reading and writing is automatically made exclusive, i.e. all reads enqueued before a write are executed first, then the single write is executed, then more reads can be executed (those enqueued after the write).

📝 Requirements

  • iOS 8.0+
  • Swift 3.0+

📦 Installation

Carthage

github "nodes-ios/SwiftSafe" ~> 2.0

For Swift 2.2 release:
github "nodes-ios/SwiftSafe" ~> 1.0

CocoaPods

pod 'SwiftSafe'

🎓 Usage

Let's say you're writing a thread-safe NSData cache. You'd like it to use CREW access to maximize performance.

class MyCache {
	private let storage: NSMutableDictionary = NSMutableDictionary()
	public func hit(key: String) -> NSData? {
		let found = self.storage[key]
		if let found = found {
			print("Hit for key \(key) -> \(found)")
		} else {
			print("Miss for key \(key)")
		}
		return found
	}
	public func update(key: String, value: NSData) {
		print("Updating \(key) -> \(value)")
		self.storage[key] = value
	}
}

This is the first implementation. It works, but when you start calling it from multiple threads at the same time, you'll encounter inconsistencies and race conditions - meaning you'll be getting different results with the same sequence of actions. In more complicated cases, you might even cause a runtime crash.

The way you fix it is obviously by protecting the internal storage (note: NSDictionary is not thread-safe). Again, to be most efficient, we want to allow any number of threads reading from the cache, but only one to update it (and ensure that nobody is reading from it at that time). You can achieve these guarantees with GCD, which is what SwiftSafe does. What this API brings to the table, however, is the simple and obvious naming.

Let's see how we can make our cache thread-safe in a couple lines of code.

import SwiftSafe

class MyCache {
	private let storage: NSMutableDictionary = NSMutableDictionary()
	private let safe: Safe = CREW()
	public func hit(key: String) -> NSData? {
		var found: NSData?
		safe.read {
			found = self.storage[key]
			if let found = found {
				print("Hit for key \(key) -> \(found)")
			} else {
				print("Miss for key \(key)")
			}
		}
		return found
	}
	public func update(key: String, value: NSData) {
		safe.write {
			print("Updating \(key) -> \(value)")
			self.storage[key] = value
		}
	}
}

That's it! Just import the library, create a Safe object which follows the concurrency mode you're trying to achieve (CREW in this case) and wrap your accesses to the shared resource in read and write calls. Note that read closures always block the caller thread, whereas write don't. If you ever have a call which both updates your resource and reads from it, make sure to split that functionality into the writing and reading part. This will make it much easier to reason about and parallelize.

👉 Bottom line

Even though it might sound unnecessary to some, understandable and correct methods of synchronization will save you days of debugging and many headaches. :)

💙 Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

✌️ License

MIT

👽 Author

Honza Dvorsky - http://honzadvorsky.com, @czechboy0

You might also like...
Modern thread-safe and type-safe key-value observing for Swift and Objective-C

Now Archived and Forked PMKVObserver will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork o

Class for logging excessive blocking on the main thread
Class for logging excessive blocking on the main thread

Watchdog Class for logging excessive blocking on the main thread. It watches the main thread and checks if it doesn’t get blocked for more than define

A thread safe throttle written in Swift

SwiftThrottle - A thread safe throttle written in Swift licensed under MIT. Introduction This throttle is intended to prevent the program from crashing

Example project guide you schedules multiple thread for network requests in RxSwift, which is optimize your app's performance better.
Example project guide you schedules multiple thread for network requests in RxSwift, which is optimize your app's performance better.

RxSwift-Multi-Threading-Example Example project guide you schedules multiple thread for network requests in RxSwift, which is optimize your app's perf

A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety
A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety

A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety. Type Safe No more userInfo dictionary and Downcasting,

Track is a thread safe cache write by Swift. Composed of DiskCache and MemoryCache which support LRU.
Track is a thread safe cache write by Swift. Composed of DiskCache and MemoryCache which support LRU.

Track is a thread safe cache write by Swift. Composed of DiskCache and MemoryCache which support LRU. Features Thread safe: Implement by dispatch_sema

A guard to help you check if you make UI changes not in main thread
A guard to help you check if you make UI changes not in main thread

ODUIThreadGuard ODUIThreadGuard is a guard to help check if you make UI changes not in main thread. As Xcode 9 embedded this function into Xcode, ther

Type-safe thread-local storage in Swift
Type-safe thread-local storage in Swift

Threadly is a Swift µframework that allows for type-safe thread-local storage. What is Thread-Local Storage? Thread-local storage (TLS) lets you defin

🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

A thread safe, performant, feature rich image fetcher
A thread safe, performant, feature rich image fetcher

PINRemoteImage Fast, non-deadlocking parallel image downloader and cache for iOS PINRemoteImageManager is an image downloading, processing and caching

A declarative, thread safe, and reentrant way to define code that should only execute at most once over the lifetime of an object.

SwiftRunOnce SwiftRunOnce allows a developer to mark a block of logic as "one-time" code – code that will execute at most once over the lifetime of an

Demonstration of using Tasks and TaskGroup to thread a calculation.

TasksTest Demonstration of using Tasks and TaskGroup to thread a calculation. The calculation takes place in a separate Swift class that can be reused

Remote shell using libssh2 with Objective-C, thread safe implementation.

NSRemoteShell Remote shell using libssh2 with Objective-C. Thread safe implementation. Available as Swift Package. git libssh2 prebuilt binaries are r

Thread -safe access to a lazily retrieved value, with optional validity checking

SerialUpdatingValue Thread-safe access to a lazily retrieved value, with optional validity checking Motivation Swift's Structured Concurrency provides

OTAtomics - Multi-platform Swift thread-safe atomics library

OTAtomics Multi-platform Swift thread-safe atomics library. The library has full

A barebone, thread-safe Redux-like container for Swift.

SwiftTinyRedux SwiftTinyRedux is a barebone, thread-safe Redux-like container for Swift. It features a minimal API and supports composable reducers. I

An elegant, fast, thread-safe, multipurpose key-value storage, compatible with all Apple platforms.
An elegant, fast, thread-safe, multipurpose key-value storage, compatible with all Apple platforms.

KeyValueStorage An elegant, fast, thread-safe, multipurpose key-value storage, compatible with all Apple platforms. Supported Platforms iOS macOS watc

**`withCheckedContinuation`'s body will run on background thread in case of starting from main-actor.**
**`withCheckedContinuation`'s body will run on background thread in case of starting from main-actor.**

ConcurrencyContinuationReproduce Differences of Concurrency behaviors between Xcode 14.0 and 14.1 Xcode 14.0 iOS 13+: Runs on main (inherited same con

Clocks made out of clocks made out of code

Clocks I came across this digital clock composed out of a set of analog clocks, created by Humans Since 1982, in a tweet, so I decided to remake it in

Comments
  • Fix error in .podspec file

    Fix error in .podspec file

    The .podspec repository was outdated using the old references to the repository of @czechboy0 that doesn't exist anymore and that implies that all the dependencies using this repository fails in pod install.

    The following issues were solved in this pull request:

    1. Fix the source of the repository.
    2. Fix the issue with the prefix v in the tag version.

    The validation using pod spec lint was correct. Nevertheless before run pod spec lint to validate the specs I recommend read this issue regarding Swift 3.0 validation specs.

    Also it would be great if the pull request is merged please update the Specs repository in CocoaPods using pod trunk push [XXX.podspec] because the last version submitted is 0.1 and does not exist anymore.

    opened by Vkt0r 6
  • Pod ref is missing for version 0.1

    Pod ref is missing for version 0.1

    With the pull request I made before I fix the issue with the SwiftSafe.podspec, but if necessary to make the pod trunk push SwiftSafe.podspec with the respective credentials for the owner of project to be SwiftSafe available again in the Specs of Cocopoads with the correct version.

    Right now is impossible to build Buildasaur because it depends of BuildaUtils that depends on SwiftSafe.

    It would be great 😅 integrate the library in the Specs to continue the contribution on Buildasaur.

    opened by Vkt0r 11
Owner
Nodes - iOS
Nodes - iOS
Promises is a modern framework that provides a synchronization construct for Swift and Objective-C.

Promises Promises is a modern framework that provides a synchronization construct for Objective-C and Swift to facilitate writing asynchronous code. I

Google 3.7k Dec 24, 2022
A synchronization framework for Core Data.

Core Data Ensembles Author: Drew McCormack Created: 29th September, 2013 Last Updated: 15th February, 2017 Ensembles 2 is now available for purchase a

Drew McCormack 1.6k Dec 6, 2022
Robust CloudKit synchronization: offline editing, relationships, shared and public databases, field-level deltas, and more.

CloudCore CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift. Features Leveraging NSPersist

deeje cooley 123 Dec 31, 2022
Save data to the database, real-time synchronization, user authentication.

Shop List App on development stage... description description description description description ??️ License This project is licensed under the MIT L

Sergey Lukaschuk 0 Nov 2, 2021
Joplin - an open source note taking and to-do application with synchronization capabilities for Windows, macOS, Linux, Android and iOS. Forum: https://discourse.joplinapp.org/

Joplin® is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are sea

Laurent 33.7k Dec 30, 2022
A Modern Concurrency and Synchronization for Swift.

##Features Simple Atomic<T> class for numbers and strings. Uncomplicated dispatch keyword for firing off background routines. Awesome Chan<T> for conc

Josh Baker 421 Jun 30, 2022
A minimalistic, thread safe, non-boilerplate and super easy to use version of Active Record on Core Data.

Skopelos A minimalistic, thread-safe, non-boilerplate and super easy to use version of Active Record on Core Data. Simply all you need for doing Core

Alberto De Bortoli 235 Sep 9, 2022
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
MemoryCache - type-safe, thread-safe memory cache class in Swift

MemoryCache is a memory cache class in swift. The MemoryCache class incorporates LRU policies, which ensure that a cache doesn’t

Yusuke Morishita 74 Nov 24, 2022