Using WeakRef for Caching
The following example uses WeakRef to implement a cache. If calculating certain data is time-consuming, we can use weak references to cache the results and prevent excessive caching that could lead to OOM.
import std.ref.{WeakRef, CleanupPolicy}
public interface Cacheable<T> {
static func reCalculate() : T
}
public class Data <: Cacheable<Data> {
public var number: Int64
init(n : Int64) {
number = n
}
public static func reCalculate(): Data {
// Simulate calculation.
println("re-calculations!")
let data = Data(321)
return data
}
}
public class Cache<T> where T <: Object & Cacheable<T> {
private var cache : WeakRef<T>
public init(data: T) {
cache = WeakRef<T>(data, CleanupPolicy.DEFERRED) // Here, we select the DEFERRED policy to store data for as long as possible.
}
public func getData(): T {
match(cache.value) {
case Some(x) => x
case None =>
// Perform recalculation if the GC releases the data in the cache.
let data = T.reCalculate()
cache = WeakRef<T>(data, CleanupPolicy.DEFERRED)
data
}
}
public func clear() : Unit {
cache.clear()
}
}
main () {
let data = Data(123)
var c = Cache<Data>(data)
println(c.getData().number) // Read data directly from the cache. Recalculation is not required.
println(c.getData().number) // Read data directly from the cache. Recalculation is not required.
c.clear() // Clear the cache.
println(c.getData().number) // Perform recalculation.
return 0
}
Results:
123
123
re-calculations!
321