File: OperationCache.swift

package info (click to toggle)
golang-github-odeke-em-cache 0.0~git20151107.0.baf8e436-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 88 kB
  • sloc: makefile: 2
file content (53 lines) | stat: -rw-r--r-- 1,684 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//
//  OperationCache.swift
//
//  Created by Indragie Karunaratne on 8/3/15.
//

import Foundation

public struct Expirable<ValueType> {
    public let expiryDate: NSDate
    public let value: ValueType
    
    public var expired: Bool {
        return NSDate().compare(expiryDate) == .OrderedDescending
    }
}

public func ==<ValueType: Equatable>(lhs: Expirable<ValueType>, rhs: Expirable<ValueType>) -> Bool {
    return lhs.expiryDate == rhs.expiryDate && lhs.value == rhs.value
}

/// Swift port of https://github.com/odeke-em/cache/blob/master/cache.go
///
/// Lockless & thread safe with support for multiple concurrent readers
/// and a single writer.
public class OperationCache<KeyType: Hashable, ValueType> {
    public typealias ExpirableType = Expirable<ValueType>
    private let queue = dispatch_queue_create("com.indragie.OperationCache", DISPATCH_QUEUE_CONCURRENT)
    private var storage = [KeyType: ExpirableType]()
    
    public var snapshot: Zip2Sequence<[KeyType], [ExpirableType]> {
        var sequence: Zip2Sequence<[KeyType], [ExpirableType]>? = nil
        dispatch_sync(queue) {
            sequence = zip(self.storage.keys.array, self.storage.values.array)
        }
        return sequence!
    }
    
    public subscript(key: KeyType) -> Expirable<ValueType>? {
        get {
            var value: ExpirableType?
            dispatch_sync(queue) { value = self.storage[key] }
            if let value = value where value.expired {
                self[key] = nil
                return nil
            }
            return value
        }
        set {
            dispatch_barrier_async(queue) { self.storage[key] = newValue }
        }
    }
}