I'm getting warning with this line:
// Initialization of 'UnsafeMutablePointer<thread_act_t>' (aka 'UnsafeMutablePointer<UInt32>') results in a dangling pointer
// 1. Implicit argument conversion from '[thread_act_t]' (aka 'Array<UInt32>') to 'UnsafePointer<thread_act_t>' (aka 'UnsafePointer<UInt32>') produces a pointer valid only for the duration of the call to 'init(mutating:)'
// 2. Use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope
var thread_list: thread_act_array_t? = UnsafeMutablePointer(mutating: [thread_act_t]())
So it's asking to enclose the whole access scope of thread_list
inside Array.withUnsafeBufferPointer
closure.
But I'm not able to make the change compile.
Here is the whole thing:
import SwiftUI
struct CPUUsageView: View {
var body: some View {
Text("\(Self.cpuUsage())")
}
// Source for cpuUsage(): https://stackoverflow.com/a/44134397/7786555
static func cpuUsage() -> Double {
var kr: kern_return_t
var task_info_count: mach_msg_type_number_t
task_info_count = mach_msg_type_number_t(TASK_INFO_MAX)
var tinfo = [integer_t](repeating: 0, count: Int(task_info_count))
kr = task_info(mach_task_self_, task_flavor_t(TASK_BASIC_INFO), &tinfo, &task_info_count)
if kr != KERN_SUCCESS {
return -1
}
// Initialization of 'UnsafeMutablePointer<thread_act_t>' (aka 'UnsafeMutablePointer<UInt32>') results in a dangling pointer
// 1. Implicit argument conversion from '[thread_act_t]' (aka 'Array<UInt32>') to 'UnsafePointer<thread_act_t>' (aka 'UnsafePointer<UInt32>') produces a pointer valid only for the duration of the call to 'init(mutating:)'
// 2. Use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope
var thread_list: thread_act_array_t? = UnsafeMutablePointer(mutating: [thread_act_t]())
var thread_count: mach_msg_type_number_t = 0
defer {
if let thread_list = thread_list {
vm_deallocate(mach_task_self_, vm_address_t(bitPattern: thread_list), vm_size_t(Int(thread_count) * MemoryLayout<thread_t>.stride) )
}
}
kr = task_threads(mach_task_self_, &thread_list, &thread_count)
if kr != KERN_SUCCESS {
return -1
}
var tot_cpu: Double = 0
if let thread_list = thread_list {
for j in 0 ..< Int(thread_count) {
var thread_info_count = mach_msg_type_number_t(THREAD_INFO_MAX)
var thinfo = [integer_t](repeating: 0, count: Int(thread_info_count))
kr = thread_info(thread_list[j], thread_flavor_t(THREAD_BASIC_INFO),
&thinfo, &thread_info_count)
if kr != KERN_SUCCESS {
return -1
}
let threadBasicInfo = convertThreadInfoToThreadBasicInfo(thinfo)
if threadBasicInfo.flags != TH_FLAGS_IDLE {
tot_cpu += (Double(threadBasicInfo.cpu_usage) / Double(TH_USAGE_SCALE)) * 100.0
}
} // for each thread
}
return tot_cpu
}
static func convertThreadInfoToThreadBasicInfo(_ threadInfo: [integer_t]) -> thread_basic_info {
var result = thread_basic_info()
result.user_time = time_value_t(seconds: threadInfo[0], microseconds: threadInfo[1])
result.system_time = time_value_t(seconds: threadInfo[2], microseconds: threadInfo[3])
result.cpu_usage = threadInfo[4]
result.policy = threadInfo[5]
result.run_state = threadInfo[6]
result.flags = threadInfo[7]
result.suspend_count = threadInfo[8]
result.sleep_time = threadInfo[9]
return result
}
}
struct CPUUsageView_Previews: PreviewProvider {
static var previews: some View {
CPUUsageView()
}
}