Skip to content

Instantly share code, notes, and snippets.

@hassanvfx
Last active February 7, 2021 06:29
Show Gist options
  • Save hassanvfx/abfcd543b18eb0c92598ec2e0e40f286 to your computer and use it in GitHub Desktop.
Save hassanvfx/abfcd543b18eb0c92598ec2e0e40f286 to your computer and use it in GitHub Desktop.
class TestModel{
var id = UUID().uuidString
}
struct TestStruct:Hashable{
var id = UUID().uuidString
}
let cache = FactoryCache()
cache.register { TestModel() }
let item:TestModel = cache.fetch( TestStruct() )
let item2:TestModel = cache.fetch( "1234" )
let item3:TestModel = cache.fetch( "1234" )
let item4:TestModel = cache.fetch( "1234" )
print(item.id)
print(item2.id)
print(item3.id)
print(item4.id)
import UIKit
public class FactoryCache {
public typealias MakerClosure<Item> = ()->Item
typealias CacheType = NSCache<NSString, InstanceWrapper>
struct CacheWrapper{
var storage: CacheType = NSCache()
}
struct FactoryWrapper<Item>{
var maker:MakerClosure<Item>
}
class InstanceWrapper{
var item:Any
init(item:Any){
self.item = item
}
}
private var queue = DispatchQueue(label: UUID().uuidString)
private var semaphore = DispatchSemaphore(value: 0)
private var factories = [Int:Any]()
private var caches = [Int: CacheWrapper]()
}
extension FactoryCache{
public func register<Item>(limit:Int = 99,factory:@escaping MakerClosure<Item>){
queue.async {
let key = ObjectIdentifier(Item.self).hashValue
let wrapper = FactoryWrapper(maker: factory)
let storage = CacheType()
let cache = CacheWrapper(storage: storage)
storage.countLimit = limit
self.factories[key] = wrapper
self.caches[key] = cache
self.semaphore.signal()
}
semaphore.wait(timeout: .distantFuture)
}
}
extension FactoryCache{
public func fetch<Keyer:Hashable,Item>(_ item: Keyer) -> Item {
var result:Item?
queue.async {
let key = NSString(string: "\(item.hashValue)")
let factoryKey = ObjectIdentifier(Item.self).hashValue
guard let cache = self.caches[factoryKey] else {
assert(false,"factory not registered")
fatalError()
}
if let wrapper = cache.storage.object(forKey: key) {
result = wrapper.item as? Item
self.semaphore.signal()
return
}
guard let factory = self.factories[factoryKey] as? FactoryWrapper<Item> else {
assert(false,"factory not registered")
fatalError()
}
let instance = factory.maker()
cache.storage.setObject(InstanceWrapper(item: instance), forKey: key)
result = instance
self.semaphore.signal()
}
semaphore.wait(timeout: .distantFuture)
guard let output = result else {
assert(false,"failed to build")
fatalError()
}
return output
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment