Code Quality Rank: L5
Monthly Downloads: 0
Programming language: Swift
License: MIT License
Tags: Thread    
Latest version: v2.0.2

EKI alternatives and similar libraries

Based on the "Thread" category

Do you think we are missing an alternative of EKI or a related project?

Add another 'Thread' Library


DEPRECATED Eki # Swift 3+ offer a new elegant api for dispatch that makes EKI useless

License Platform Language Issues Cocoapod Reference Status

Eki lets you manage easily concurrency in your apps. This framework makes Grand Central Dispatch easy and fun to use.


  • iOS 8.0+ / Mac OS X 10.10+
  • Xcode 6.3


Internally GCD manages a pool of threads which process dispatch queues and invoke blocks submitted to them.

Main and Global queues

  • Main
  • UserInteractive
  • UserInitiated
  • Default
  • Utility
  • Background

The queues are ordered in descending priority order.

You access them like so:



You 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.async {
    // Block 1
}.async {
    // Block 2
// Or by submitting an array of blocks:
let blocks = [{
    // Block 1
}, {
    // Block 2

Custom Queue

Create your own queue (serial or concurrent):

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

Dispatch barrier

Dispatch a block asynchronously with barrier:

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

Iterate on a Queue

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

Current Queue

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

Take 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

// 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 Initialization

A timer can be paused or stopped.


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


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:

  // Do some stuff when a resource is available

// Or

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

Use with cocoapods

Add pod 'Eki' to your Podfile and run pod install.

*Note that all licence references and agreements mentioned in the EKI README section above are relevant to that project's source code only.