Contents

pavankumar-n-46/swiftsafecollections

A production-ready Swift package providing **thread-safe data structures** with configurable locking strategies. Built with Test-Driven Development (TDD) and Protocol-Oriented Programming (POP).

✨ Features

  • πŸ”’ Thread-Safe: All operations are atomic and concurrency-safe
  • ⚑ High Performance: Optimized read-write locks for concurrent reads
  • 🎯 Protocol-Oriented: Clean, composable architecture
  • πŸ§ͺ Fully Tested: 86 comprehensive tests with 100% coverage
  • πŸ“¦ Zero Dependencies: Pure Swift implementation
  • 🌍 Cross-Platform: iOS, macOS, tvOS, watchOS, visionOS, and Linux
  • πŸš€ Swift 6 Ready: Strict concurrency compliant

πŸ“¦ Data Structures

| Structure | Description | Use Case | |-----------|-------------|----------| | ThreadSafeArray<Element> | Thread-safe array with subscript access | General-purpose ordered collection | | ThreadSafeDictionary<Key, Value> | Thread-safe key-value storage | Caching, configuration management | | ThreadSafeSet<Element> | Thread-safe unique elements | Deduplication, membership testing | | ThreadSafeQueue<Element> | FIFO queue | Task queues, message passing | | ThreadSafeStack<Element> | LIFO stack | Undo/redo, parsing | | ThreadSafeDeque<Element> | Double-ended queue | Sliding windows, breadth-first search |

πŸš€ Installation

Swift Package Manager

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/pavankumar-n-46/SwiftSafeCollections", from: "1.0.0")
]

Or in Xcode:

  1. File β†’ Add Package Dependencies
  2. Enter: https://github.com/pavankumar-n-46/SwiftSafeCollections
  3. Select version and add to your target

πŸ’‘ Quick Start

ThreadSafeArray

import ThreadSafeDataStructures

let array = ThreadSafeArray<Int>()

// Thread-safe operations
array.append(1)
array.append(2)
array.append(3)

print(array[0])  // Optional(1)
print(array.count)  // 3

// Functional operations
let doubled = array.map { $0 * 2 }  // [2, 4, 6]

ThreadSafeDictionary

let cache = ThreadSafeDictionary<String, Data>()

// Labeled subscript for value access
cache[key: "user123"] = userData
let data = cache[key: "user123"]

// Traditional dictionary operations
cache.updateValue(newData, forKey: "user123")
cache.removeValue(forKey: "user123")

// Atomic snapshot
let snapshot = cache.snapshot()

ThreadSafeSet

let userIds = ThreadSafeSet<String>()

// Set operations
userIds.insert("user1")
userIds.insert("user2")

// Set algebra
let set1: ThreadSafeSet<Int> = [1, 2, 3]
let set2: ThreadSafeSet<Int> = [3, 4, 5]

let union = set1.union(set2)  // [1, 2, 3, 4, 5]
let intersection = set1.intersection(set2)  // [3]

ThreadSafeQueue (FIFO)

let queue = ThreadSafeQueue<String>()

queue.enqueue("first")
queue.enqueue("second")
queue.enqueue("third")

print(queue.dequeue())  // Optional("first")
print(queue.peek())     // Optional("second")

ThreadSafeStack (LIFO)

let stack = ThreadSafeStack<Int>()

stack.push(1)
stack.push(2)
stack.push(3)

print(stack.pop())   // Optional(3)
print(stack.peek())  // Optional(2)

ThreadSafeDeque

let deque = ThreadSafeDeque<Int>()

deque.appendBack(1)
deque.appendFront(0)
deque.appendBack(2)

print(deque.removeFront())  // Optional(0)
print(deque.removeBack())   // Optional(2)

πŸ”§ Advanced Usage

Custom Locking Strategies

All data structures support configurable locking strategies:

// Read-Write Lock (default - optimized for read-heavy workloads)
let array1 = ThreadSafeArray<Int>(lock: ReadWriteLock())

// Mutex Lock (simple exclusive locking)
let array2 = ThreadSafeArray<Int>(lock: MutexLock())

// Dispatch Queue Lock (GCD-based)
let array3 = ThreadSafeArray<Int>(lock: DispatchQueueLock())

Concurrent Operations

let cache = ThreadSafeDictionary<String, Data>()

await withTaskGroup(of: Void.self) { group in
    for i in 0..<1000 {
        group.addTask {
            cache[key: "key\(i)"] = Data()
        }
    }
}

print(cache.count)  // 1000

Functional Programming

let numbers = ThreadSafeArray<Int>()
(1...100).forEach { numbers.append($0) }

// Map, filter, reduce
let evens = numbers.filter { $0 % 2 == 0 }
let doubled = numbers.map { $0 * 2 }

// ForEach with side effects
var sum = 0
numbers.forEach { sum += $0 }

πŸ—οΈ Architecture

Design Patterns

  • Decorator Pattern: Thread-safe wrappers around Swift collections
  • Strategy Pattern: Configurable locking mechanisms
  • Protocol-Oriented Design: Composable protocol hierarchy

Protocol Hierarchy

ThreadSafeCollection (base protocol)
    β”œβ”€β”€ count: Int
    β”œβ”€β”€ isEmpty: Bool
    └── removeAll()

ThreadSafeSequence: ThreadSafeCollection
    β”œβ”€β”€ forEach(_:)
    β”œβ”€β”€ map(_:)
    └── filter(_:)

ThreadSafeSubscriptable: ThreadSafeCollection
    └── subscript(index:) -> Element?

Locking Strategies

| Strategy | Implementation | Best For | |----------|---------------|----------| | ReadWriteLock | pthread_rwlock_t | Read-heavy workloads | | MutexLock | pthread_mutex_t | Balanced read/write | | DispatchQueueLock | DispatchQueue + barrier | GCD integration |

πŸ§ͺ Testing

The package includes 86 comprehensive tests covering:

  • βœ… Basic operations (CRUD)
  • βœ… Edge cases (empty, nil, bounds)
  • βœ… Functional operations (map, filter, forEach)
  • βœ… Concurrency scenarios (race conditions, deadlocks)
  • βœ… Set algebra operations
  • βœ… FIFO/LIFO behavior

Run tests:

swift test

πŸ“Š Performance

Optimized for production use:

  • Concurrent Reads: Multiple threads can read simultaneously
  • Exclusive Writes: Barrier-based writes ensure data integrity
  • Lock-Free Snapshots: Atomic copy-on-read for consistency
  • O(1) Operations: Where possible (append, peek, etc.)

πŸ”’ Thread Safety Guarantees

All operations are:

  • βœ… Atomic: Operations complete without interruption
  • βœ… Isolated: No data races or race conditions
  • βœ… Consistent: Snapshots provide point-in-time views
  • βœ… Sendable: Swift 6 concurrency compliant

Important: Sendable Requirement

All generic type parameters require Sendable conformance:

// βœ… Works - Int is Sendable
let numbers = ThreadSafeArray<Int>()

// βœ… Works - Sendable struct
struct User: Sendable { let id: String }
let users = ThreadSafeArray<User>()

// ❌ Won't compile - Non-Sendable class
class UnsafeData { var value: Int }
let data = ThreadSafeArray<UnsafeData>()  // Error!

Why? Locks protect collection storage, but not element mutations. Sendable ensures elements themselves are thread-safe.

πŸ“š Documentation

Full API documentation is available in the source code. Each type includes:

  • Comprehensive doc comments
  • Usage examples
  • Thread-safety guarantees
  • Performance characteristics

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass (swift test)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

Built with:

  • Swift 6.0
  • Swift Testing framework
  • Protocol-Oriented Programming principles
  • Test-Driven Development methodology

πŸ“ž Support


Made with ❀️ for the Swift community

Package Metadata

Repository: pavankumar-n-46/swiftsafecollections

Default branch: main

README: README.md