concurrency-kit 1.1.1

concurrency-kit 1.1.1

Astemir Eleev维护。



  • Astemir Eleev

concurrency-kit Awesome

Platforms Language CocoaPod Build Status Coverage License

最后更新:2019年3月31日。

如果您喜欢这个项目,请给它点个 star ⭐ 这将表示您对创建者的赞赏,并将帮助他人发现这个存储库。

✍️关于

🚄适用于iOS开发([Task]、[Atomic]、[Lock]等)的并发抽象框架。

🏗安装

CocoaPods

concurrency-kit通过CocoaPods提供。

pod 'concurrency-kit', '~> 1.1.1' 

手动操作

您始终可以使用复制粘贴源代码的方法。😄或者您可以将框架编译并包含到您的项目中。

🔥功能

  • 原子操作 - 以多种形式实现(通用型、整型、布尔型)的同步原语。
    • 快速. 在内部使用了一个互斥锁(pthread_mutex_lock),比OSSpinLock更高效,比NSLock更快。
    • 可抛出异常。您可以安全地抛出Errors,并能够委托处理。
  • - 包含了多个锁,例如
    • UnfairLock - 一个会让尝试获取锁的线程在一个循环(“自旋”)中等待,并反复检查锁是否可用。
    • ReadWriteLock -读/写锁允许对仅读操作进行并发访问,而写入操作则需要独占访问。
    • Mutex - 允许只在一个特定的代码区域中有一个线程是活动的。
  • DispatchQueue+Extensions - 扩展了 DispatchQueue,其中 asyncAfteronce 方法增加了便利性。
  • 任务 - 是一个执行特定工作并通常与其他任务并行的作业单元。
    • 任务可以是 分组 的 —— 意味着您可以将任务组合起来,类似于 Futures & Promises,并按顺序执行它们。
    • 任务可以是 顺序执行 的 —— 意味着您可以将不同的 groups 组合起来并并发执行它们。无需重复使用 DispatchGroupenter/leave)。
  • 具有状态的运算 - 是一个自定义的 Operation 类,通过使用 AtomicsEnum 类型支持现代的 Swifty 状态管理。
  • 彻底测试过

📚示例

任务

为了创建一个 Task,您只需要使用 Task 结构和后置闭包语法。

let uploadingTask = Task { controller in
  uploader(photos) { result in 
    switch result {
      case .success:
        controller.finish()
      case .failure(let error):          
        controller.fail(with error)
    }
  }
}
        
uploadingTask.perform { outcome in
  handle(outcome)
}

您可以将任务分组,这样并发操作将会按顺序执行,一个接一个。然后,您可以在链中添加一个完成闭包来处理结果

let filesToUpload = [file, photo, video, xml]

let group = Task.group(fileToUpload)
group.perform { outcome in 
  handle(outcome)
}

或者您可以将一组任务并发执行。它们将被异步执行,如果是可能的,它们将平行或并发执行,这取决于 GCD

let filesToUpload = [file, photo, video, xml]

let group = Task.sequence(filesToUpload)
group.perform { outcome in 
  handle(outcome)
}

具有状态的运算

具有更多“Swifty”状态管理系统的运算,其中状态是一个枚举类型,具有多种可能的情况。为了演示典型用法,让我们定义一个新的自定义网络请求运算

class NetworkStatefulOperation: StatefullOperation {

  // MARK: - Properties
  
  private let callback: (StatefullOperation?) -> Void
  private let service: NetworkService             
  private let dataHandler: Parsable            
            
  // MARK: - Initializers
  
  init(_ service: NetworkService, _ dataHandler: Parser, callback: @escaping (StatefullOperation?) -> Void) {
    self.service = service
    self.dataHandler = dataHandler
    self.callback = callback
  }
  
  // MARK: - Overrides
  
  override func executableSection() {
    service.dataTask { [weak self] result in 
      self?.dataHandler.parse(result)
      self?.finishIfNotCancelled()
      self?.callback(self)
    }
  }
}

然后,NetworkStatefulOperation 类的使用方法相当简单

// 1. Create an instance of `NetworkStatefulOperation` class:
let networkiOperation = NetworkStatefulOperation(service, parser) {
  // 3. As soon as the operation is finished, this closure will be executed with the operation state that can futher be handled to properly update the UI:
  updateUI(with: $0.state)
}
// 2. Then call the `start` method:
networkOperation.start()

原子操作

保证了在多个异步调度队列中安全修改一个属性。只需将一个属性包裹在 Atomic 类型中即可。

let atomic = Atomic(0)

DispatchQueue.global().async {
  atomic.modify { $0 + 1 }
}

DispatchQueue.global().async {
  atomic.modify { $0 + 1 }
}

您还可以使用性能更加友好的AtomicIntAtomicBool类,因此涉及不到动态调度(尽管Swift编译器足够智能,会应用称为编译时泛型专用化的编译器优化[查看详情])。

读写锁

一种同步原语,用于解决读者-写者问题之一

let rwLock = ReadWriteLock()

rwLock.writeLock()
sharedValue += 1
rwLock.unlock()

或者您还可以限制读取访问,这样其他线程将无法在释放锁之前读取属性被修改后的值

let rwLock = ReadWriteLock()

rwLock.readLock()
sharedValue += 1
rwLock.unlock()

不公平锁

导致试图获取锁的线程简单地在一个循环中等待(“自旋”),同时反复检查锁是否可用

let unfairLock = UnfairLock()

unfairLock.lock()
sharedValue += 1
unfairLock.unlock()

互斥锁

用于保护共享资源。互斥锁归获取它的任务所有。在给定的代码区域中,只有一个线程是活动的。

let mutex = Mutex()

mutex.withCriticalScope {
  return sharedValue += 1
}

派发队列

有一个便捷的方法,无需传递.now() + time即可进行异步调用

DispatchQueue.main.asyncAfter(seconds: 2.5) {
  expectation.fulfill()
}

此外,还返回了:DispatchQueue.once

// The following concurrentQueue is called multiple times, though the caughtValue will be set to value only once.
concurrentQueue.async {
  DispatchQueue.once(token: "caught") {
    caughtValue = value
  }
}

👨‍💻作者

Astemir Eleev

🔖许可证

该项目可在MIT许可证下使用。