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
1613using  namespace  std ; 
1714using  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: " "  [--datagram|--twoway|--oneway] [topic]" 
20+ }
2021
2122int 
2223main (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: " "  [--datagram|--twoway|--oneway] [topic]" 
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" 
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." 
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