Eki
Eki copied to clipboard
[DEPRECATED] Eki lets you manage easily concurrency in your apps. This framework make Grand Central Dispatch API more friendly and fun to use.
DEPRECATED Eki # Swift 3+ offer a new elegant api for dispatch that makes EKI useless
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
.