From 5030d22ec53c663bb93a45b69ec3587d98693614 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Sat, 19 Aug 2023 09:39:18 +0200 Subject: [PATCH] fix: trying to fix the crash by fixing some data racing in the widgets (#1578) --- Kit/Widgets/BarChart.swift | 104 +++++++++++++------------------- Kit/Widgets/Battery.swift | 70 ++++++++++++--------- Kit/Widgets/Label.swift | 5 +- Kit/Widgets/LineChart.swift | 107 +++++++++++---------------------- Kit/Widgets/Memory.swift | 22 ++----- Kit/Widgets/Mini.swift | 104 +++++++++++++------------------- Kit/Widgets/NetworkChart.swift | 52 +++------------- Kit/Widgets/PieChart.swift | 22 ++----- Kit/Widgets/Stack.swift | 6 +- Kit/Widgets/State.swift | 10 +-- Kit/Widgets/Tachometer.swift | 22 ++----- Kit/module/module.swift | 5 +- Kit/module/widget.swift | 6 +- Modules/Sensors/popup.swift | 2 +- Modules/Sensors/values.swift | 10 +-- 15 files changed, 198 insertions(+), 349 deletions(-) diff --git a/Kit/Widgets/BarChart.swift b/Kit/Widgets/BarChart.swift index b65e2f7c..9265bcc7 100644 --- a/Kit/Widgets/BarChart.swift +++ b/Kit/Widgets/BarChart.swift @@ -16,11 +16,11 @@ public class BarChart: WidgetWrapper { private var boxState: Bool = true private var frameState: Bool = false private var colorState: Color = .systemAccent - private var colors: [Color] = Color.allCases - private var value: [[ColorValue]] = [[]] - private var pressureLevel: DispatchSource.MemoryPressureEvent = .normal - private var colorZones: colorZones = (0.6, 0.8) + + private var _value: [[ColorValue]] = [[]] + private var _pressureLevel: DispatchSource.MemoryPressureEvent = .normal + private var _colorZones: colorZones = (0.6, 0.8) private var boxSettingsView: NSView? = nil private var frameSettingsView: NSView? = nil @@ -38,7 +38,7 @@ public class BarChart: WidgetWrapper { if let previewConfig = config!["Preview"] as? NSDictionary { configuration = previewConfig if let value = configuration["Value"] as? String { - self.value = value.split(separator: ",").map{ ([ColorValue(Double($0) ?? 0)]) } + self._value = value.split(separator: ",").map{ ([ColorValue(Double($0) ?? 0)]) } } } } @@ -53,7 +53,7 @@ public class BarChart: WidgetWrapper { self.colors = self.colors.filter{ !unsupportedColors.contains($0.key) } } if let color = configuration["Color"] as? String { - if let defaultColor = colors.first(where: { "\($0.self)" == color }) { + if let defaultColor = self.colors.first(where: { "\($0.self)" == color }) { self.colorState = defaultColor } } @@ -76,8 +76,8 @@ public class BarChart: WidgetWrapper { } if preview { - if self.value.isEmpty { - self.value = [[ColorValue(0.72)], [ColorValue(0.38)]] + if self._value.isEmpty { + self._value = [[ColorValue(0.72)], [ColorValue(0.38)]] } self.setFrameSize(NSSize(width: 36, height: self.frame.size.height)) self.invalidateIntrinsicContentSize() @@ -92,12 +92,21 @@ public class BarChart: WidgetWrapper { public override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) + var value: [[ColorValue]] = [] + var pressureLevel: DispatchSource.MemoryPressureEvent = .normal + var colorZones: colorZones = (0.6, 0.8) + self.queue.sync { + value = self._value + pressureLevel = self._pressureLevel + colorZones = self._colorZones + } + var width: CGFloat = Constants.Widget.margin.x*2 var x: CGFloat = 0 let lineWidth = 1 / (NSScreen.main?.backingScaleFactor ?? 1) let offset = lineWidth / 2 - switch self.value.count { + switch value.count { case 0, 1: width += 10 + (offset*2) case 2: @@ -155,23 +164,23 @@ public class BarChart: WidgetWrapper { let widthForBarChart = box.bounds.width let partitionMargin: CGFloat = 0.5 - let partitionsMargin: CGFloat = (CGFloat(self.value.count - 1)) * partitionMargin / CGFloat(self.value.count - 1) - let partitionWidth: CGFloat = (widthForBarChart / CGFloat(self.value.count)) - CGFloat(partitionsMargin.isNaN ? 0 : partitionsMargin) + let partitionsMargin: CGFloat = (CGFloat(value.count - 1)) * partitionMargin / CGFloat(value.count - 1) + let partitionWidth: CGFloat = (widthForBarChart / CGFloat(value.count)) - CGFloat(partitionsMargin.isNaN ? 0 : partitionsMargin) let maxPartitionHeight: CGFloat = box.bounds.height x += offset - for i in 0.. Void)? = nil - public var shadowSize: CGSize + internal var queue: DispatchQueue public init(_ type: widget_t, title: String, frame: NSRect) { self.type = type self.title = title self.shadowSize = frame.size + self.queue = DispatchQueue(label: "eu.exelban.Stats.WidgetWrapper.\(type.rawValue).\(title)") super.init(frame: frame) } @@ -372,6 +372,7 @@ public class MenuBar { private var moduleName: String private var menuBarItem: NSStatusItem? = nil private var active: Bool = false + private var queue: DispatchQueue private var combinedModules: Bool { Store.shared.bool(key: "CombinedModules", defaultValue: false) @@ -394,6 +395,7 @@ public class MenuBar { init(moduleName: String) { self.moduleName = moduleName + self.queue = DispatchQueue(label: "eu.exelban.Stats.MenuBar.\(moduleName)") self.oneView = Store.shared.bool(key: "\(self.moduleName)_oneView", defaultValue: self.oneView) self.view.identifier = NSUserInterfaceItemIdentifier(rawValue: moduleName) diff --git a/Modules/Sensors/popup.swift b/Modules/Sensors/popup.swift index 1f711a10..30d609e4 100644 --- a/Modules/Sensors/popup.swift +++ b/Modules/Sensors/popup.swift @@ -1091,7 +1091,7 @@ private class ModeButtons: NSStackView { if !Store.shared.bool(key: "Sensors_turnOffFanAlert", defaultValue: false) { let alert = NSAlert() alert.messageText = localizedString("Turn off fan") - alert.informativeText = localizedString("You are going to turn off the fan. That is not recommended action that can broke your mac, are you sure you want to do that?") + alert.informativeText = localizedString("You are going to turn off the fan. This is not recommended action that can damage your mac, are you sure you want to do that?") alert.showsSuppressionButton = true alert.addButton(withTitle: localizedString("Turn off")) alert.addButton(withTitle: localizedString("Cancel")) diff --git a/Modules/Sensors/values.swift b/Modules/Sensors/values.swift index 0d9a1e14..bfbd18b9 100644 --- a/Modules/Sensors/values.swift +++ b/Modules/Sensors/values.swift @@ -49,16 +49,16 @@ public protocol Sensor_p { var formattedPopupValue: String { get } } -public struct Sensors_List: Codable { +public class Sensors_List: Codable { private var queue: DispatchQueue = DispatchQueue(label: "eu.exelban.Stats.Sensors.SynchronizedArray", attributes: .concurrent) private var list: [Sensor_p] = [] public var sensors: [Sensor_p] { get { - self.queue.sync{self.list} + self.queue.sync{ self.list } } - set(newValue) { - self.queue.sync { + set { + self.queue.async(flags: .barrier) { self.list = newValue } } @@ -76,7 +76,7 @@ public struct Sensors_List: Codable { try container.encode(wrappers, forKey: .sensors) } - public init(from decoder: Decoder) throws { + required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let wrappers = try container.decode([Sensor_w].self, forKey: .sensors) self.sensors = wrappers.map { $0.sensor }