CocoaPods trunk is moving to be read-only. Read more on the blog, there are 14 months to go.
| TestsTested | ✓ |
| LangLanguage | SwiftSwift |
| License | MIT |
| ReleasedLast Release | Oct 2015 |
| SPMSupports SPM | ✗ |
Maintained by Jérémy Marchand.
Eki is a framework to manage easily concurrency in your apps that wraps the powerful API Grand Central Dispatch.
Internally GCD manages a pool of threads which process dispatch queues and invoke blocks submitted to them.
MainUserInteractiveUserInitiatedDefaultUtilityBackgroundThe queues are ordered in descending priority order.
You access them like so:
Queue.BackgroundYou dispatch a block on queue asynchronously by using async or synchronously by using 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
...
}You can send multiple blocks to a queue:
Queue.Utility <<< {
// Block 1
} <<< {
// Block 2
}
// Or by submitting an array of blocks:
let blocks = [{
// Block 1
}, {
// Block 2
}]
Queue.Utility.async(blocks)Create your own queue (serial or concurrent):
let queue = Queue(name:"QueueName", kind:.Concurrent)
queue.async{
...
}Dispatch a block asynchronously with barrier:
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 queueTake notice that will work only on Custom Queues created with the designed initializer Queue(name:String, kind:Queue.Custom.Kind), the Main queue and Global queues.
A task represents a block to be dispatched on a queue.
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.A task can be chained with a block or an another 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
}A group allows to associate multiple blocks to be dispatched asynchronously.
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.There is two ways to track group’s blocks execution:
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.Execute a block once and only once.
let once = OnceDispatcher() // Store it somewhere
...
once {
// Executed only one time
}A timer allows to schedule a block on a specified queue with an interval or a date.
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 InitializationA timer can be paused or stopped.
timer.pause()
timer.start()
timer.stop()A timer can be repeated, use a date…
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()There is three kinds of semaphore:
| Kind | Initial Resource(s) |
|---|---|
| Binary | 1 |
| Barrier | 0 |
| Counting(resource:UInt16) | custom |
Initialize a semaphore:
let sem = Semaphore(.Binary)
let customSem = Semaphore(resource:5)
You can decrement/increment semaphore’s resource by using wait/signal methods:
sem.wait()
// Do some stuff when a resource is available
sem.signal()
// Or
sem--
...
sem++Or by using the perform convenient method with a closure:
sem.perform {
// Do some stuff when a resource is available
}
// Or
sem <<< {
...
}A mutex is essentially the same thing as a binary semaphore except that only the block that locked the resource is supposed to unlock it.
let m = Mutex()
...
m.sync {
// Do some stuff when a mutext is available
}
// Or
m <<< {
...
}LockedObject is convenient class to lock access to an object with an internal mutext.
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
...
}