Skip to content

Instantly share code, notes, and snippets.

@stephancasas
Created March 2, 2024 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephancasas/b1559009a43e1b919cda1de6fc7092f0 to your computer and use it in GitHub Desktop.
Save stephancasas/b1559009a43e1b919cda1de6fc7092f0 to your computer and use it in GitHub Desktop.
A type which records both the process identifier and the time at which the represented instance was dispatched.
//
// EquatableProcess.swift
//
// Created by Stephan Casas on 3/2/24.
//
/// A value type which records both the process identifier and the time at which the
/// represented instance was dispatched — providing a unique identity for a single
/// application instance.
struct EquatableProcess: Identifiable, Hashable {
let pid: pid_t;
let launchTime: Int;
/// Create a new `EquatableProcess` for the given process identifier.
init?(_ pid: pid_t) {
guard let launchTime = EquatableProcess.getSysctlInfo(
for: pid
)?.kp_proc.p_starttime.tv_sec else {
return nil;
}
self.pid = pid;
self.launchTime = launchTime
}
/// Create a new `EquatableProcess` for the process which owns the given `AXUIElement`.
/// - Parameter element: An accessibility element owned by a running application process.
init?(for element: AXUIElement) {
var pid: pid_t = 0;
guard AXUIElementGetPid(element, &pid) == .success else {
return nil;
}
self.init(pid);
}
/// Get the sysctl information value for the process with the given process identifier.
private static func getSysctlInfo(for pid: pid_t) -> kinfo_proc? {
var mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid];
var procInfo = kinfo_proc();
var procInfoSize = MemoryLayout<kinfo_proc>.size;
guard sysctl(
&mib, .init(mib.count),
&procInfo, &procInfoSize,
nil, 0
) == 0 else {
return nil;
}
return procInfo;
}
var id: Int { self.hashValue }
static func ==(lhs: EquatableProcess, rhs: pid_t) -> Bool {
lhs == EquatableProcess(rhs)
}
static func ==(lhs: pid_t, rhs: EquatableProcess) -> Bool {
EquatableProcess(lhs) == rhs
}
}
// MARK: - pid_t + EquatableProcess
extension pid_t {
var equatableProcess: EquatableProcess? { .init(self) }
static func ==(lhs: pid_t, rhs: Optional<EquatableProcess>) -> Bool {
guard let rhs = rhs else {
return false
}
return lhs == rhs;
}
static func ==(lhs: Optional<EquatableProcess>, rhs: pid_t) -> Bool {
guard let lhs = lhs else {
return false
}
return lhs == rhs;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment