macos: auto-expire cached screen contents
parent
839d89f2dc
commit
e69c756c89
|
|
@ -1926,39 +1926,43 @@ extension Ghostty.SurfaceView {
|
||||||
/// Caches a value for some period of time, evicting it automatically when that time expires.
|
/// Caches a value for some period of time, evicting it automatically when that time expires.
|
||||||
/// We use this to cache our surface content. This probably should be extracted some day
|
/// We use this to cache our surface content. This probably should be extracted some day
|
||||||
/// to a more generic helper.
|
/// to a more generic helper.
|
||||||
///
|
|
||||||
// TODO:
|
|
||||||
// - Auto-expire the data so it doesn't take memory
|
|
||||||
fileprivate class CachedValue<T> {
|
fileprivate class CachedValue<T> {
|
||||||
private var value: Value?
|
private var value: T?
|
||||||
private let fetch: () -> T
|
private let fetch: () -> T
|
||||||
private let duration: Duration
|
private let duration: Duration
|
||||||
|
private var expiryTask: Task<Void, Never>?
|
||||||
struct Value {
|
|
||||||
var value: T
|
|
||||||
var expires: ContinuousClock.Instant
|
|
||||||
}
|
|
||||||
|
|
||||||
init(duration: Duration, fetch: @escaping () -> T) {
|
init(duration: Duration, fetch: @escaping () -> T) {
|
||||||
self.duration = duration
|
self.duration = duration
|
||||||
self.fetch = fetch
|
self.fetch = fetch
|
||||||
}
|
}
|
||||||
|
|
||||||
func get() -> T {
|
deinit {
|
||||||
let now = ContinuousClock.now
|
expiryTask?.cancel()
|
||||||
if let value {
|
}
|
||||||
// If the value isn't expired just return it
|
|
||||||
if value.expires > now {
|
|
||||||
return value.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value is expired, clear it
|
func get() -> T {
|
||||||
self.value = nil
|
if let value {
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have a value (or it expired). Fetch and store.
|
// We don't have a value (or it expired). Fetch and store.
|
||||||
let result = fetch()
|
let result = fetch()
|
||||||
self.value = .init(value: result, expires: now + duration)
|
let now = ContinuousClock.now
|
||||||
|
let expires = now + duration
|
||||||
|
self.value = result
|
||||||
|
|
||||||
|
// Schedule a task to clear the value
|
||||||
|
expiryTask = Task { [weak self] in
|
||||||
|
do {
|
||||||
|
try await Task.sleep(until: expires)
|
||||||
|
self?.value = nil
|
||||||
|
self?.expiryTask = nil
|
||||||
|
} catch {
|
||||||
|
// Task was cancelled, do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue