Last active
October 7, 2022 11:54
-
-
Save eneko/c8b92a6005ad8e669ced69509575e361 to your computer and use it in GitHub Desktop.
Thread-safe, ordered-dictionary-backed, actor-based LRU cache
This file contains hidden or 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
// | |
// LRUCacheActor.swift | |
// LRUCacheActor | |
// | |
// Created by Eneko Alonso on 9/5/21. | |
// | |
import Foundation | |
import OrderedCollections | |
/// A simple actor-based LRU cache, backed by an OrderedDictionary, implemented | |
/// for illustration purposes to compare performance between actors and serial | |
/// dispatch queues. | |
/// - Read performance is O(n), far from the ideal O(1). | |
/// - Write performance is O(1) (amortized) | |
@available(iOS 15, macOS 12, *) | |
public actor LRUCacheActor<Key: Hashable, Value> { | |
var store: OrderedDictionary<Key, Value> = [:] | |
var capacity: Int | |
public init(capacity: Int) async { | |
self.capacity = max(capacity, 1) | |
} | |
/// Read an item from the cache | |
/// - complexity: O(n) due to removal of item from current position | |
public func item(for key: Key) -> Value? { | |
guard let value = store.removeValue(forKey: key) else { | |
return nil | |
} | |
store[key] = value | |
return value | |
} | |
/// Add a new item to the cache | |
/// - complexity: O(1) (assuming the cache does not contain more items than it's capacity) | |
public func set(item: Value?, for key: Key) { | |
while store.count >= capacity { | |
store.removeFirst() | |
} | |
store[key] = item | |
} | |
/// Number of elements in the cache | |
/// - complexity: O(1) | |
public var count: Int { store.count } | |
/// Test if the cache contains any elements | |
/// - complexity: O(1) | |
public var isEmpty: Bool { store.isEmpty } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment