Skip to content

Instantly share code, notes, and snippets.

@kayoslab
Created September 5, 2017 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kayoslab/9abf045d6fd7dab05355e01f908e4b2b to your computer and use it in GitHub Desktop.
Save kayoslab/9abf045d6fd7dab05355e01f908e4b2b to your computer and use it in GitHub Desktop.
A simple Generic Queue with different priority Levels
import Foundation
/// Different Priority Levels for Queue Objects
public enum QueuePriority: Int {
case low = 0
case medium = 1
case high = 2
/// Returns the priority Type for using the main Queue.
fileprivate static func mainQueuePriority() -> QueuePriority {
return .medium
}
}
/// Subclass this Class with a non generic Type.
/// - note: Please override the init function with a private
/// access modifactor and create a singleton, so you
/// can ensure that there are no more Queues as you
/// are expecting.
internal class QueueHandler<T> {
private var queues: Set<Queue<T>>
/// Checks if any Queue contains an Element waiting for execution.
internal final var isEmpty: Bool {
var isEmpty: Bool = true
queues.forEach { (queue) in
if queue.isEmpty == false {
isEmpty = false
}
}
return isEmpty
}
/// Initializes a new QueueHandler with a mainQueue
/// If you override this class make the init function private
/// and create a singleton of your `QueueHandler` Subclass.
internal init() {
queues = [Queue(with: .mainQueuePriority())]
}
/// Enqueue an Element into a given prioritie's Queue.
/// - parameters:
/// - element: Generic Element which can be Enqueued
/// - priority: Element of `QueuePriority` representing the Priority
/// which should be used for the execution of this particular
/// Element.
internal final func enqueue(_ element: T, with priority: QueuePriority = QueuePriority.mainQueuePriority()) {
queues.insert(Queue<T>(with: priority))
queues.first(where: { $0.priority == priority })?.enqueue(element)
}
/// Deques an Element with the highest priority first.
/// - returns: The highest prioritized generic Elemnent of any queue
internal final func dequeue() -> T? {
var element: T?
queues.sorted(by: >).forEach({ (queue) in
if !queue.isEmpty {
element = queue.dequeue()
return
}
})
return element
}
/// Shows the next Element with a given Priority.
/// - parameters:
/// - priority: Element of `QueuePriority` representing the Priority
/// which should be used to retrieve the next Element of
/// the given Queueu.
internal final func peak(with priority: QueuePriority = QueuePriority.mainQueuePriority()) -> T? {
return queues.first(where: { $0.priority == priority })?.peek()
}
}
/// Implementation of a simple Queue Structure, which
/// can be initialized and compared with their initialized
/// Priority.
fileprivate final class Queue<T> {
private var queue: Array<T> = []
fileprivate let priority: QueuePriority
fileprivate var isEmpty: Bool {
return queue.isEmpty
}
/// Creates a new Queue Structure with the Priority
/// of a MainQueue.
fileprivate init() {
priority = QueuePriority.mainQueuePriority()
}
fileprivate init(with priority: QueuePriority = .medium) {
self.priority = priority
}
fileprivate final func enqueue(_ element: T) {
queue.append(element)
}
fileprivate final func dequeue() -> T? {
if !isEmpty {
return queue.removeFirst()
} else {
return nil
}
}
fileprivate final func peek() -> T? {
if !isEmpty {
return queue.first
} else {
return nil
}
}
}
/// To Compare multiple Queues and store them in a Set
/// we have to implement the hashValue which is defined
/// in the `Hashable` Protocol.
extension Queue: Hashable {
internal var hashValue: Int {
return priority.hashValue
}
}
/// Types that conform to `Hashable` need to conform to
/// `Equatable` as well.
extension Queue: Equatable {
static func == (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority == rhs.priority
}
static func != (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority != rhs.priority
}
}
/// To compare multiple Queues by their Priority we
/// also need to implement the Comparable Protocol.
extension Queue: Comparable {
static func < (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority.rawValue < rhs.priority.rawValue
}
static func > (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority.rawValue > rhs.priority.rawValue
}
static func <= (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority.rawValue <= rhs.priority.rawValue
}
static func >= (lhs: Queue, rhs: Queue) -> Bool {
return lhs.priority.rawValue >= rhs.priority.rawValue
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment