Eki 2.0.0

Eki 2.0.0

测试测试通过
语言语言 SwiftSwift
许可 MIT
发布最后发布2015年10月
SPM支持SPM

Jérémy Marchand维护。



Eki 2.0.0

Eki

logo

Eki是一个框架,用于轻松管理应用程序中的并发,它封装了功能强大的API Grand Central Dispatch。

要求

  • iOS 8.0+ / macOS 10.10+
  • Xcode 6.3

队列

内部GCD管理一个线程池,该线程池处理派遣队列并调用提交给它们的块。

主队列和全局队列

  • 主队列
  • UserInteractive
  • UserInitiated
  • 默认
  • Utility
  • Background

队列按照优先级降序排列。

您可以通过以下方式访问它们

Queue.Background

派遣

您可以使用async异步或使用sync同步来在队列上派遣块

// Asynchronously
Queue.Utility.async {
    ...
}
// Or asynchronously using the operator shortcut
Queue.Utility <<< {
    ...
}

// Synchronously
Queue.Utility.sync { // Eki will prevent deadlock if you submit a sync on the current queue
    ...
}

您可以向队列发送多个块

Queue.Utility <<< {
    // Block 1
} <<< {
    // Block 2
}
// Or by submitting an array of blocks:
let blocks = [{
    // Block 1
}, {
    // Block 2
}]
Queue.Utility.async(blocks)

自定义队列

创建您自己的队列(串行或并发)

let queue = Queue(name:"QueueName", kind:.Concurrent)
queue.async{
    ...
}

派遣屏障

使用屏障异步派遣块

let queue:Queue = Queue(name:"QueueName", type:.Concurrent)
...
queue |<| { // Or barrierAsync { }
    // This block will be executed on the queue only after all previous submitted blocks have been executed
} <<< {
    // This block will be executed only after the previous barrier block have completed
}

计划

Queue.Background.after(2) {
    // Do some stuff on Background after 2 seconds
}

在队列上迭代

Queue.Background.iterate(4) { i in
    // Do some stuff on Background 4 times
}

当前队列

Queue.current // Get current queue
Queue.Background.isCurrent // Check if background is current queue

请注意,这将仅在由设计初始化器 Queue(name:String, kind:Queue.Custom.Kind) 创建的 自定义队列主队列全局队列 上工作。

任务

任务表示要在队列上派遣的块。

let t = Task(queue:.Utility) {
    ...
}
// Or
let t = Queue.Utility + {
    ...
}

t.async() // Dispatch asynchronously

group.async(t) // Dispatch on a group

let tasks:[Task] = ...
g.async(tasks) // Tasks dispatched on a group.

任务可以用 block 或另一个 Task 连接

t.chain {
    // Executed after t on same queue
}.chain(Task(queue:.Main) {
    // Executed after previous block on the main queue
})
t.async()

// Or chain directly after async and use the operator shortcut
t.async() <> {  
    // Executed after t on same queue
} <> Queue.Main + {
    // Executed after previous block on the main queue
}

组允许将多个将被异步派遣的块相关联。

let g = Group(queue:.Utility) // By default the group queue is Background

g.async {
    // Block dispatched on the group's queue.
} <<< {
    // Block dispatched on the group's queue using the operator.
} <<< Task(queue:.Main) {
    // Block dispatched on the Main queue (see Task).
}

let blocks:[()-> Void] = ...
g.async(blocks) // Blocks dispatched on the group's queue.

有两种方式来跟踪组块的执行

g.notify {
    // Block executed on the group queue when blocks previously dispatched on the group have been executed.
}
g.notify(Queue.Main + {
    // Block executed on the Main queue when blocks previously dispatched on the group have been executed.
})

g.wait() // Wait on the current process the group's blocks execution.

once

执行一次并只执行一次

let once = OnceDispatcher() // Store it somewhere
...
once {
    // Executed only one time
}

定时器

定时器允许以一定的间隔或在指定日期安排一个队列中的块。

let timer = Timer.scheduleWithInterval(2, onQueue: .Background) {
   // Do some stuff on Background after 2 seconds
}
// Equivalent to:
let timer = Timer(queue: .Background, interval: 2)
timer.handler {
  // Do some stuff on Background after 2 seconds
}
timer.start() // Timers are paused at Initialization

定时器可以暂停或停止。

timer.pause()
timer.start()
timer.stop()

定时器可以重复,使用日期...

let date: NSDate = ...
let timer = Timer(queue: .Background, date: date)
timer.repeatInterval = 4
timer.tolerance =  1 // Add some tolerance
timer.handler {
  // Do some stuff on Background on specified date and after every 4 seconds approximately
}
timer.start()

信号量

有三种类型的信号量

类型 初始资源
二进制 1
屏障 0
计数(资源: UInt16) 自定义

初始化信号量

let sem = Semaphore(.Binary)
let customSem = Semaphore(resource:5)

您可以使用 wait/signal 方法递减/递增信号量的资源。

sem.wait()
  // Do some stuff when a resource is available
sem.signal()

// Or
sem--
  ...
sem++

或使用带有闭包的方便的 perform 方法。

sem.perform {
    // Do some stuff when a resource is available
}

// Or
sem <<< {
    ...
}

互斥锁

互斥锁本质上与二进制信号量相同,只是锁定资源的块应该解锁资源。

let m = Mutex()
...
m.sync {
    // Do some stuff when a mutext is available
}

// Or
m <<< {
  ...
}

受保护对象

LockedObject 是一个方便的类,可以使用内部 互斥锁 锁定对对象的访问。

let myobj = MyObject()
let l = LockedObject(myobj)
...
l.access { obj in
    // Only one process at a time will access the locked object
}

// Or
l <<< { obj in
  ...
}