Skip to content

Commit

Permalink
Use CtrlCHandler in IceStorm/clock (Swift) (#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardnormier authored Feb 5, 2025
1 parent 721f405 commit b932dbf
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 55 deletions.
30 changes: 30 additions & 0 deletions swift/IceStorm/clock/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// swift-tools-version: 5.9

import Foundation
import PackageDescription

guard let iceHome = ProcessInfo.processInfo.environment["ICE_HOME"] else {
fatalError("ICE_HOME environment variable not set")
}

let package = Package(
name: "clock",
platforms: [
.macOS(.v14)
],
dependencies: [.package(name: "ice", path: iceHome)],
targets: [
.executableTarget(
name: "Publisher",
dependencies: [.product(name: "Ice", package: "ice"), .product(name: "IceStorm", package: "ice")],
exclude: ["slice-plugin.json"],
plugins: [.plugin(name: "CompileSlice", package: "ice")]
),
.executableTarget(
name: "Subscriber",
dependencies: [.product(name: "Ice", package: "ice"), .product(name: "IceStorm", package: "ice")],
exclude: ["slice-plugin.json"],
plugins: [.plugin(name: "CompileSlice", package: "ice")]
),
]
)
64 changes: 28 additions & 36 deletions swift/IceStorm/clock/Sources/Publisher/main.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) ZeroC, Inc.

import Foundation
import PromiseKit
import Ice
import IceStorm

Expand All @@ -19,29 +18,15 @@ enum Option: String {
case oneway = "--oneway"
}

func run() -> Int32 {
func run(ctrlCHandler: Ice.CtrlCHandler) async -> Int32 {
do {
var args = [String](CommandLine.arguments.dropFirst())
signal(SIGTERM, SIG_IGN)
signal(SIGINT, SIG_IGN)

let communicator = try Ice.initialize(args: &args, configFile: "config.pub")
defer {
communicator.destroy()
}

let sigintSource = DispatchSource.makeSignalSource(signal: SIGINT, queue: DispatchQueue.main)
sigintSource.setEventHandler {
communicator.destroy()
}
sigintSource.resume()

let sigtermSource = DispatchSource.makeSignalSource(signal: SIGTERM, queue: DispatchQueue.main)
sigtermSource.setEventHandler {
communicator.destroy()
}
sigtermSource.resume()

var option: Option = .none
var topicName = "time"

Expand All @@ -67,7 +52,7 @@ func run() -> Int32 {
}

guard let base = try communicator.propertyToProxy("TopicManager.Proxy"),
let manager = try checkedCast(prx: base, type: IceStorm.TopicManagerPrx.self) else {
let manager = try await checkedCast(prx: base, type: IceStorm.TopicManagerPrx.self) else {
print("invalid proxy")
return 1
}
Expand All @@ -77,10 +62,10 @@ func run() -> Int32 {
//
var topic: IceStorm.TopicPrx!
do {
topic = try manager.retrieve(topicName)
topic = try await manager.retrieve(topicName)
} catch is IceStorm.NoSuchTopic {
do {
topic = try manager.create(topicName)
topic = try await manager.create(topicName)
} catch is IceStorm.TopicExists {
print("temporary error. try again.")
return 1
Expand All @@ -91,7 +76,7 @@ func run() -> Int32 {
// Get the topic's publisher object, and create a Clock proxy with
// the mode specified as an argument of this application.
//
guard var publisher = try topic.getPublisher() else {
guard var publisher = try await topic.getPublisher() else {
print("Error getting publisher proxy")
return 1
}
Expand All @@ -113,27 +98,34 @@ func run() -> Int32 {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY HH:mm:ss"

let t = DispatchSource.makeTimerSource()
t.schedule(deadline: .now(), repeating: .seconds(1))
t.setEventHandler {
do {
try clock.tick(dateFormatter.string(from: Date()))
} catch is CommunicatorDestroyedException {
t.suspend()
exit(0)
} catch {
t.suspend()
print("Error: \(error)\n")
communicator.destroy()
exit(1)
// Send a tick every second until cancelled
let task = Task {
while true {
do {
try await clock.tick(dateFormatter.string(from: Date()))
} catch let error as Ice.LocalException {
print("tick invocation failed with: \(error.message)")
}
try await Task.sleep(for: .seconds(1))
}
}
t.activate()
Dispatch.dispatchMain()

let signal = await ctrlCHandler.catchSignal()
print("Caught signal \(signal), exiting...")

task.cancel()
do {
try await task.value
} catch is CancellationError {
// expected
}

return 0
} catch {
print("Error: \(error)\n")
return 1
}
}

exit(run())
let ctrlCHandler = Ice.CtrlCHandler()
exit(await run(ctrlCHandler: ctrlCHandler))
3 changes: 3 additions & 0 deletions swift/IceStorm/clock/Sources/Publisher/slice-plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"sources": ["../../slice/Clock.ice"]
}
32 changes: 13 additions & 19 deletions swift/IceStorm/clock/Sources/Subscriber/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,14 @@ enum Option: String {
case oneway = "--oneway"
}

func run() -> Int32 {
func run(ctrlCHandler: CtrlCHandler) async -> Int32 {
do {
var args = [String](CommandLine.arguments.dropFirst())
signal(SIGTERM, SIG_IGN)
signal(SIGINT, SIG_IGN)

let communicator = try Ice.initialize(args: &args, configFile: "config.sub")
defer {
communicator.destroy()
}

let sigintSource = DispatchSource.makeSignalSource(signal: SIGINT,
queue: DispatchQueue.global())
let sigtermSource = DispatchSource.makeSignalSource(signal: SIGTERM,
queue: DispatchQueue.global())
sigintSource.setEventHandler { communicator.shutdown() }
sigtermSource.setEventHandler { communicator.shutdown() }
sigintSource.resume()
sigtermSource.resume()

args = try communicator.getProperties().parseCommandLineOptions(prefix: "Clock", options: args)

var topicName = "time"
Expand Down Expand Up @@ -98,7 +86,7 @@ func run() -> Int32 {
}

guard let base = try communicator.propertyToProxy("TopicManager.Proxy"),
let manager = try checkedCast(prx: base, type: IceStorm.TopicManagerPrx.self) else {
let manager = try await checkedCast(prx: base, type: IceStorm.TopicManagerPrx.self) else {
print("invalid proxy")
return 1
}
Expand All @@ -108,10 +96,10 @@ func run() -> Int32 {
//
let topic: IceStorm.TopicPrx!
do {
topic = try manager.retrieve(topicName)
topic = try await manager.retrieve(topicName)
} catch is IceStorm.NoSuchTopic {
do {
topic = try manager.create(topicName)
topic = try await manager.create(topicName)
} catch is IceStorm.TopicExists {
print("temporary error. try again.")
return 1
Expand Down Expand Up @@ -161,20 +149,26 @@ func run() -> Int32 {
}

do {
_ = try topic.subscribeAndGetPublisher(theQoS: qos, subscriber: subscriber)
_ = try await topic.subscribeAndGetPublisher(theQoS: qos, subscriber: subscriber)
} catch is IceStorm.AlreadySubscribed {
// Must never happen when subscribing with an UUID
precondition(id != nil)
print("reactivating persistent subscriber")
}

let signal = await ctrlCHandler.catchSignal()
print("Caught signal \(signal), exiting...")

communicator.shutdown()
communicator.waitForShutdown()
try topic.unsubscribe(subscriber)

try await topic.unsubscribe(subscriber)
return 0
} catch {
print("Error: \(error)\n")
return 1
}
}

exit(run())
let ctrlCHandler = CtrlCHandler()
exit(await run(ctrlCHandler: ctrlCHandler))
3 changes: 3 additions & 0 deletions swift/IceStorm/clock/Sources/Subscriber/slice-plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"sources": ["../../slice/Clock.ice"]
}
File renamed without changes.

0 comments on commit b932dbf

Please sign in to comment.