Skip to content
This repository has been archived by the owner on Oct 21, 2020. It is now read-only.

Latest commit

 

History

History
316 lines (255 loc) · 6.93 KB

README.md

File metadata and controls

316 lines (255 loc) · 6.93 KB

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

License Platform Language Issues Cocoapod Reference Status

logo

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

Requirements

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

Queue

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:

Queue.Background

Dispatch

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
}]
Queue.Utility.async(blocks)

Custom Queue

Create your own queue (serial or concurrent):

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

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
}

Schedule

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.

Task

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
}

Group

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.

Once

Execute a block once and only once.

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

Timer

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.

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()

Semaphore

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 <<< {
	...
}

Mutex

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

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.