48 lines
1.8 KiB
Swift
48 lines
1.8 KiB
Swift
//
|
|
// Copyright 2024 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
/// This class can be used by ``SDSDatabaseStorage`` to learn of
|
|
/// database writes by other processes.
|
|
///
|
|
/// * `notifyChanged` should be called after every write
|
|
/// transaction completes.
|
|
/// * `callback` is invoked when a write from another process
|
|
/// is detected.
|
|
final class SDSCrossProcess: Sendable {
|
|
|
|
private let notifyTokens: [DarwinNotificationCenter.ObserverToken]
|
|
|
|
init(callback: @escaping @Sendable @MainActor () -> Void) {
|
|
var notifyTokens: [DarwinNotificationCenter.ObserverToken] = []
|
|
let block = { (_: DarwinNotificationCenter.ObserverToken) -> Void in
|
|
// the addObserver calls below execute this block on the main thread so we should already be isolated
|
|
// but there's no way to tell the compiler this with these old APIs, so we tell it to assume we are.
|
|
MainActor.assumeIsolated {
|
|
callback()
|
|
}
|
|
}
|
|
|
|
// listen to everyone but our self; then when posting post our own type
|
|
let currentAppContextType = CurrentAppContext().type
|
|
for appContextType in AppContextType.allCases {
|
|
if appContextType == currentAppContextType { continue }
|
|
notifyTokens.append(DarwinNotificationCenter.addObserver(name: .sdsCrossProcess(for: appContextType), queue: .main, block: block))
|
|
}
|
|
self.notifyTokens = notifyTokens
|
|
}
|
|
|
|
deinit {
|
|
for notifyToken in notifyTokens {
|
|
if DarwinNotificationCenter.isValid(notifyToken) {
|
|
DarwinNotificationCenter.removeObserver(notifyToken)
|
|
}
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
func notifyChanged() {
|
|
DarwinNotificationCenter.postNotification(name: .sdsCrossProcess(for: CurrentAppContext().type))
|
|
}
|
|
}
|