Created
September 5, 2017 14:44
-
-
Save kayoslab/9abf045d6fd7dab05355e01f908e4b2b to your computer and use it in GitHub Desktop.
A simple Generic Queue with different priority Levels
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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