Skip to content

concurrency is a modern, testable Swift framework that provides elegant abstractions for Grand Central Dispatch (GCD) primitives

License

Notifications You must be signed in to change notification settings

space-code/concurrency

Repository files navigation

concurrency: A collection of concurrency primitives

concurrency

License Swift Compatibility Platform Compatibility CI

Description

concurrency is a modern, testable Swift framework that provides elegant abstractions for Grand Central Dispatch (GCD) primitives. Built with testability in mind, it enables you to write concurrent code that's easy to test and maintain.

Features

✨ Type-Safe Queue Abstractions - Clean interfaces for main, global, and custom queues
πŸ§ͺ Built for Testing - Comes with dedicated test doubles for unit testing
⚑ Lightweight - Minimal wrapper around GCD with zero overhead
🎯 Protocol-Based - Easy to mock and inject dependencies
πŸ“± Cross-Platform - Works on iOS, macOS, tvOS, watchOS, and visionOS

Table of Contents

Requirements

Platform Minimum Version
iOS 13.0+
macOS 10.15+
tvOS 13.0+
watchOS 6.0+
visionOS 1.0+
Xcode 15.3+
Swift 5.10+

Installation

Swift Package Manager

Add the following dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/space-code/concurrency.git", from: "0.3.0")
]

Or add it through Xcode:

  1. File > Add Package Dependencies
  2. Enter package URL: https://github.com/space-code/concurrency.git
  3. Select version requirements

Quick Start

import Concurrency

// Create a queue factory
let factory = DispatchQueueFactory()

// Use the main queue for UI updates
let mainQueue = factory.main()
mainQueue.async {
    // Update UI safely
    updateLabel()
}

// Use a background queue for heavy work
let backgroundQueue = factory.global(qos: .background)
backgroundQueue.async {
    processLargeDataset()
}

Usage

Dispatch Queue Factory

The DispatchQueueFactory is your entry point for creating all types of dispatch queues:

import Concurrency

let factory = DispatchQueueFactory()

Main Queue

Perfect for UI updates and ensuring code runs on the main thread:

import Concurrency

class ViewController {
    private let factory = DispatchQueueFactory()
    private lazy var mainQueue = factory.main()
    
    func updateUI(with data: Data) {
        mainQueue.async {
            self.label.text = String(data: data, encoding: .utf8)
            self.refreshButton.isEnabled = true
        }
    }
}

Global Queue

Access system-provided concurrent queues with different quality of service levels:

import Concurrency

class DataProcessor {
    private let factory = DispatchQueueFactory()
    
    func processInBackground() {
        // High priority background work
        let userInitiatedQueue = factory.global(qos: .userInitiated)
        userInitiatedQueue.async {
            self.performCriticalProcessing()
        }
        
        // Low priority background work
        let backgroundQueue = factory.global(qos: .background)
        backgroundQueue.async {
            self.performMaintenanceTasks()
        }
    }
}

Quality of Service Levels:

  • .userInteractive - Work that is interacting with the user (animations, event handling)
  • .userInitiated - Work initiated by the user that prevents further interaction
  • .default - Default priority for work
  • .utility - Long-running tasks with user-visible progress
  • .background - Work not visible to the user (prefetching, maintenance)
  • .unspecified - Absence of QoS information`

Private Queue

Create custom queues with fine-grained control:

import Concurrency

class NetworkManager {
    private let factory = DispatchQueueFactory()
    
    // Serial queue for thread-safe access
    private lazy var serialQueue = factory.privateQueue(
        label: "com.example.network.serial",
        qos: .userInitiated,
        attributes: [],
        autoreleaseFrequency: .inherit,
        target: nil
    )
    
    // Concurrent queue for parallel processing
    private lazy var concurrentQueue = factory.privateQueue(
        label: "com.example.network.concurrent",
        qos: .utility,
        attributes: .concurrent,
        autoreleaseFrequency: .workItem,
        target: nil
    )
    
    func processRequests(_ requests: [Request]) {
        concurrentQueue.async {
            requests.forEach { request in
                self.process(request)
            }
        }
    }
}

Parameters:

  • label - Unique identifier for debugging
  • qos - Quality of service class
  • attributes - .concurrent for concurrent execution, empty for serial
  • autoreleaseFrequency - Memory management strategy
  • target - Queue to execute blocks on (advanced usage)

Testing

Concurrency includes a dedicated test target with synchronous test doubles:

import TestConcurrency
import XCTest

class ViewModelTests: XCTestCase {
    func testDataFetching() {
        // Create test queue that executes immediately
        let testQueue = TestDispatchQueue()
        let viewModel = ViewModel(queue: testQueue)
        
        // Runs block immediately
        testQueue.async {}

        // No need for expectations - execution is synchronous
        viewModel.fetchData()
        
        // Assert immediately
        XCTAssertTrue(viewModel.isLoading)
    }
}

Injecting Queues for Testability:

import Concurrency

protocol DispatchQueueType {
    func async(execute work: @escaping () -> Void)
    func sync(execute work: () -> Void)
}

extension DispatchQueue: DispatchQueueType {}

class DataManager {
    private let factory: IDispatchQueueFactory
    
    init(factory: IDispatchQueueFactory) {
        self.factory = factory
    }
    
    func loadData(completion: @escaping (Result<Data, Error>) -> Void) {
        factory.global(qos: .background).async {
            // Perform work
            let result = self.fetchData()
            completion(result)
        }
    }
}

Communication

Contributing

We love contributions! Please feel free to help out with this project. If you see something that could be made better or want a new feature, open up an issue or send a Pull Request.

Development Setup

Bootstrap the development environment:

mise install

Author

Nikita Vasilev

License

Concurrency is released under the MIT license. See LICENSE for details.


⬆ back to top

Made with ❀️ by space-code

About

concurrency is a modern, testable Swift framework that provides elegant abstractions for Grand Central Dispatch (GCD) primitives

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •