fix: moved DispatchSource.MemoryPressureEvent to custom RAMPressure enum. Fixed the crashes on some macs (#2212)

This commit is contained in:
Serhiy Mytrovtsiy
2024-11-14 17:00:19 +01:00
parent 354698a389
commit 3d0bfa456d
14 changed files with 65 additions and 43 deletions

View File

@@ -26,16 +26,12 @@ public struct RAM_Usage: Codable {
var app: Double
var cache: Double
var rawPressureLevel: UInt
var swap: Swap
var pressure: Pressure
public var usage: Double {
get { Double((self.total - self.free) / self.total) }
}
public var pressureLevel: DispatchSource.MemoryPressureEvent {
DispatchSource.MemoryPressureEvent(rawValue: self.rawPressureLevel)
}
}
public struct Swap: Codable {
@@ -44,6 +40,11 @@ public struct Swap: Codable {
var free: Double
}
public struct Pressure: Codable {
let level: Int
let value: RAMPressure
}
public class RAM: Module {
private let popupView: Popup
private let settingsView: Settings
@@ -141,10 +142,10 @@ public class RAM: Module {
switch w.item {
case let widget as Mini:
widget.setValue(value.usage)
widget.setPressure(value.pressureLevel)
widget.setPressure(value.pressure.value)
case let widget as LineChart:
widget.setValue(value.usage)
widget.setPressure(value.pressureLevel)
widget.setPressure(value.pressure.value)
case let widget as BarChart:
if self.splitValueState {
widget.setValue([[
@@ -155,7 +156,7 @@ public class RAM: Module {
} else {
widget.setValue([[ColorValue(value.usage)]])
widget.setColorZones((0.8, 0.95))
widget.setPressure(value.pressureLevel)
widget.setPressure(value.pressure.value)
}
case let widget as PieChart:
widget.setValue([
@@ -167,7 +168,7 @@ public class RAM: Module {
let free = Units(bytes: Int64(value.free)).getReadableMemory()
let used = Units(bytes: Int64(value.used)).getReadableMemory()
widget.setValue((free, used), usedPercentage: value.usage)
widget.setPressure(value.pressureLevel)
widget.setPressure(value.pressure.value)
case let widget as Tachometer:
widget.setValue([
circle_segment(value: value.app/total, color: self.appColor),
@@ -175,7 +176,7 @@ public class RAM: Module {
circle_segment(value: value.compressed/total, color: self.compressedColor)
])
case let widget as TextWidget:
var text = self.textValue
var text = "\(self.textValue)"
let pairs = TextWidget.parseText(text)
pairs.forEach { pair in
var replacement: String? = nil
@@ -203,8 +204,8 @@ public class RAM: Module {
}
case "$pressure":
switch pair.value {
case "value": replacement = value.pressureLevel.description
case "level": replacement = value.rawPressureLevel.description
case "level": replacement = "\(value.pressure.level)"
case "value": replacement = value.pressure.value.rawValue
default: return
}
default: return

View File

@@ -127,7 +127,7 @@ class Notifications: NotificationsWrapper {
if let threshold = thresholdPair.additional as? DispatchSource.MemoryPressureEvent {
self.checkDouble(
id: self.pressureID,
value: Double(value.pressureLevel.rawValue),
value: Double(value.pressure.level),
threshold: Double(threshold.rawValue),
title: title,
subtitle: "\(localizedString("Memory pressure")): \(localizedString(thresholdPair.value))"

View File

@@ -257,7 +257,7 @@ internal class Popup: PopupWrapper {
circle_segment(value: value.compressed/value.total, color: self.compressedColor)
])
self.circle?.setNonActiveSegmentColor(self.freeColor)
self.level?.setLevel(value.pressureLevel)
self.level?.setValue(value.pressure)
self.initialized = true
}
@@ -429,7 +429,7 @@ public class PressureView: NSView {
circle_segment(value: 1/3, color: NSColor.systemRed)
]
private var level: DispatchSource.MemoryPressureEvent = .normal
private var value: Pressure = Pressure(level: 1, value: .normal)
public override func draw(_ rect: CGRect) {
let arcWidth: CGFloat = 7.0
@@ -465,7 +465,7 @@ public class PressureView: NSView {
let needleEndSize: CGFloat = 2
let needlePath = NSBezierPath()
switch self.level {
switch self.value.value {
case .normal:
needlePath.move(to: CGPoint(x: self.bounds.width * 0.15, y: self.bounds.width * 0.40))
needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - needleEndSize))
@@ -478,7 +478,6 @@ public class PressureView: NSView {
needlePath.move(to: CGPoint(x: self.bounds.width * 0.85, y: self.bounds.width * 0.40))
needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - needleEndSize))
needlePath.line(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 + needleEndSize))
default: break
}
needlePath.close()
@@ -501,12 +500,12 @@ public class PressureView: NSView {
]
let rect = CGRect(x: (self.frame.width-6)/2, y: (self.frame.height-26)/2, width: 6, height: 12)
let str = NSAttributedString.init(string: "\(self.level.rawValue)", attributes: stringAttributes)
let str = NSAttributedString.init(string: "\(self.value.level)", attributes: stringAttributes)
str.draw(with: rect)
}
public func setLevel(_ level: DispatchSource.MemoryPressureEvent) {
self.level = level
public func setValue(_ newValue: Pressure) {
self.value = newValue
if self.window?.isVisible ?? true {
self.display()
}

View File

@@ -103,11 +103,11 @@ public class Portal: PortalWrapper {
self.usedField?.stringValue = Units(bytes: Int64(value.used)).getReadableMemory()
self.freeField?.stringValue = Units(bytes: Int64(value.free)).getReadableMemory()
self.swapField?.stringValue = Units(bytes: Int64(value.swap.used)).getReadableMemory()
self.pressureLevelField?.stringValue = "\(value.pressureLevel.rawValue)"
self.pressureLevelField?.stringValue = value.pressure.value.rawValue
self.usedField?.toolTip = "\(Int(value.usage.rounded(toPlaces: 2) * 100))%"
self.freeField?.toolTip = "\(Int((1-value.usage).rounded(toPlaces: 2) * 100))%"
if let level = memoryPressureLevels.first(where: { $0.additional as? DispatchSource.MemoryPressureEvent == value.pressureLevel }) {
if let level = memoryPressureLevels.first(where: { $0.additional as? RAMPressure == value.pressure.value }) {
self.pressureLevelField?.toolTip = localizedString(level.value)
}

View File

@@ -60,6 +60,13 @@ internal class UsageReader: Reader<RAM_Usage> {
var pressureLevel: Int = 0
sysctlbyname("kern.memorystatus_vm_pressure_level", &pressureLevel, &intSize, nil, 0)
var pressureValue: RAMPressure
switch pressureLevel {
case 2: pressureValue = .warning
case 4: pressureValue = .critical
default: pressureValue = .normal
}
var stringSize: size_t = MemoryLayout<xsw_usage>.size
var swap: xsw_usage = xsw_usage()
sysctlbyname("vm.swapusage", &swap, &stringSize, nil, 0)
@@ -77,13 +84,12 @@ internal class UsageReader: Reader<RAM_Usage> {
app: used - wired - compressed,
cache: purgeable + external,
rawPressureLevel: UInt(pressureLevel),
swap: Swap(
total: Double(swap.xsu_total),
used: Double(swap.xsu_used),
free: Double(swap.xsu_avail)
)
),
pressure: Pressure(level: pressureLevel, value: pressureValue)
))
return
}

View File

@@ -27,8 +27,8 @@ public struct RAM_entry: TimelineEntry {
compressed: 414629888.0,
app: 16369778688.0,
cache: 12575948800.0,
rawPressureLevel: 1,
swap: Swap(total: 0, used: 0, free: 0)
swap: Swap(total: 0, used: 0, free: 0),
pressure: Pressure(level: 1, value: .normal)
)
)
@@ -110,7 +110,7 @@ public struct RAMWidget: Widget {
HStack {
Text(localizedString("Pressure level")).font(.system(size: 12, weight: .regular)).foregroundColor(.secondary)
Spacer()
Text("\(value.rawPressureLevel)")
Text("\(value.pressure.level)")
}
}
} else {