Skip to content

Commit 648708c

Browse files
Cleanup C++ IceStorm/clock
1 parent 58853ee commit 648708c

File tree

17 files changed

+171
-226
lines changed

17 files changed

+171
-226
lines changed

cpp/IceStorm/clock/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
project(clock CXX)
4+
5+
include(../../cmake/common.cmake)
6+
7+
add_executable(publisher Publisher.cpp Clock.ice)
8+
slice2cpp_generate(publisher)
9+
target_link_libraries(publisher Ice::Ice)
10+
11+
add_executable(subscriber Subscriber.cpp Clock.ice)
12+
slice2cpp_generate(subscriber)
13+
target_link_libraries(subscriber Ice::Ice)

cpp/IceStorm/clock/Clock.ice

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
module Demo
66
{
7+
/// The interface implemented by the subscriber. It accepts time updates.
78
interface Clock
89
{
10+
/// Sends the current time to the clock.
11+
/// @param time The current time.
912
void tick(string time);
1013
}
1114
}

cpp/IceStorm/clock/Publisher.cpp

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
// Copyright (c) ZeroC, Inc.
22

3-
#ifdef _MSC_VER
4-
// For getenv
5-
# define _CRT_SECURE_NO_WARNINGS
6-
#endif
7-
83
#include "Clock.h"
4+
95
#include <Ice/Ice.h>
106
#include <IceStorm/IceStorm.h>
7+
118
#include <chrono>
129
#include <ctime>
10+
#include <future>
1311
#include <iostream>
14-
#include <thread>
1512

1613
using namespace std;
1714
using namespace Demo;
1815

19-
int run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[]);
16+
void
17+
usage(const char* name)
18+
{
19+
cerr << "Usage: " << name << " [--datagram|--twoway|--oneway] [topic]" << endl;
20+
}
2021

2122
int
2223
main(int argc, char* argv[])
@@ -25,51 +26,24 @@ main(int argc, char* argv[])
2526
Ice::registerIceUDP();
2627
#endif
2728

28-
int status = 0;
29+
// CtrlCHandler is a helper class that handles Ctrl+C and similar signals. It must be constructed at the beginning
30+
// of the program, before creating an Ice communicator or starting any thread.
31+
Ice::CtrlCHandler ctrlCHandler;
2932

30-
try
31-
{
32-
//
33-
// CtrlCHandler must be created before the communicator or any other threads are started
34-
//
35-
Ice::CtrlCHandler ctrlCHandler;
33+
// Create an Ice communicator to initialize the Ice runtime.
34+
const Ice::CommunicatorHolder communicatorHolder{argc, argv, "config.pub"};
35+
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator();
3636

37-
//
38-
// CommunicatorHolder's ctor initializes an Ice communicator,
39-
// and its dtor destroys this communicator.
40-
//
41-
const Ice::CommunicatorHolder ich(argc, argv, "config.pub");
42-
const auto& communicator = ich.communicator();
37+
// Parse command-line options.
4338

44-
ctrlCHandler.setCallback([communicator](int) { communicator->destroy(); });
45-
46-
status = run(communicator, argc, argv);
47-
}
48-
catch (const std::exception& ex)
49-
{
50-
cerr << ex.what() << endl;
51-
status = 1;
52-
}
53-
54-
return status;
55-
}
56-
57-
void
58-
usage(const string& n)
59-
{
60-
cerr << "Usage: " << n << " [--datagram|--twoway|--oneway] [topic]" << endl;
61-
}
62-
63-
int
64-
run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
65-
{
6639
enum class Option : uint8_t
6740
{
6841
None,
6942
Datagram,
7043
Twoway,
7144
Oneway
7245
};
46+
7347
Option option = Option::None;
7448
string topicName = "time";
7549
int i;
@@ -114,16 +88,15 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
11488
return 1;
11589
}
11690

117-
auto manager = Ice::checkedCast<IceStorm::TopicManagerPrx>(communicator->propertyToProxy("TopicManager.Proxy"));
91+
// Create the topic manager proxy.
92+
auto manager = communicator->propertyToProxy<IceStorm::TopicManagerPrx>("TopicManager.Proxy");
11893
if (!manager)
11994
{
12095
cerr << argv[0] << ": invalid proxy" << endl;
12196
return 1;
12297
}
12398

124-
//
125-
// Retrieve the topic.
126-
//
99+
// Retrieve the topic from IceStorm.
127100
optional<IceStorm::TopicPrx> topic;
128101
try
129102
{
@@ -142,10 +115,8 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
142115
}
143116
}
144117

145-
//
146-
// Get the topic's publisher object, and create a Clock proxy with
147-
// the mode specified as an argument of this application.
148-
//
118+
// Get the topic's publisher object, and create a Clock proxy with the mode specified as an argument of this
119+
// application.
149120
auto publisher = topic->getPublisher();
150121
if (option == Option::Datagram)
151122
{
@@ -160,27 +131,45 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
160131
publisher = publisher->ice_oneway();
161132
}
162133

134+
// Downcast the proxy to the Clock type using uncheckedCast.
163135
auto clock = Ice::uncheckedCast<ClockPrx>(publisher);
164136

165137
cout << "publishing tick events. Press ^C to terminate the application." << endl;
166-
while (true)
167-
{
168-
try
138+
139+
// Send a tick every second until cancelled in a background task.
140+
auto future = std::async(
141+
std::launch::async,
142+
[clock = std::move(clock)]()
169143
{
170-
auto now = chrono::system_clock::to_time_t(chrono::system_clock::now());
171-
char timeString[100];
172-
if (strftime(timeString, sizeof(timeString), "%x %X", localtime(&now)) == 0)
144+
while (true)
173145
{
174-
timeString[0] = '\0';
146+
try
147+
{
148+
auto now = chrono::system_clock::to_time_t(chrono::system_clock::now());
149+
char timeString[100];
150+
if (strftime(timeString, sizeof(timeString), "%x %X", localtime(&now)) == 0)
151+
{
152+
timeString[0] = '\0';
153+
}
154+
clock->tick(timeString);
155+
this_thread::sleep_for(chrono::seconds(1));
156+
}
157+
catch (const Ice::CommunicatorDestroyedException&)
158+
{
159+
break; // done
160+
}
175161
}
176-
clock->tick(timeString);
177-
this_thread::sleep_for(chrono::seconds(1));
178-
}
179-
catch (const Ice::CommunicatorDestroyedException&)
180-
{
181-
break;
182162
}
183-
}
163+
);
164+
165+
// Wait until the user presses Ctrl+C.
166+
ctrlCHandler.wait();
167+
168+
// Destroy the communicator; the next call to tick will throw CommunicatorDestroyedException.
169+
communicator->destroy();
170+
171+
// Wait for the background task to complete.
172+
future.wait();
184173

185174
return 0;
186175
}

0 commit comments

Comments
 (0)