Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cpp/IceStorm/clock/Clock.ice
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

module Demo
{
/// The interface implemented by the subscriber. It accepts time updates.
interface Clock
{
/// Sends the current time to the clock.
/// @param time The current time.
void tick(string time);
}
}
130 changes: 65 additions & 65 deletions cpp/IceStorm/clock/Publisher.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
// Copyright (c) ZeroC, Inc.

#ifdef _MSC_VER
// For getenv
# define _CRT_SECURE_NO_WARNINGS
#endif

#include "Clock.h"

#include <Ice/Ice.h>
#include <IceStorm/IceStorm.h>

#include <chrono>
#include <ctime>
#include <future>
#include <iostream>
#include <thread>

using namespace std;
using namespace Demo;

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

int
main(int argc, char* argv[])
Expand All @@ -25,51 +26,24 @@ main(int argc, char* argv[])
Ice::registerIceUDP();
#endif

int status = 0;

try
{
//
// CtrlCHandler must be created before the communicator or any other threads are started
//
Ice::CtrlCHandler ctrlCHandler;

//
// CommunicatorHolder's ctor initializes an Ice communicator,
// and its dtor destroys this communicator.
//
const Ice::CommunicatorHolder ich(argc, argv, "config.pub");
const auto& communicator = ich.communicator();
// CtrlCHandler is a helper class that handles Ctrl+C and similar signals. It must be constructed at the beginning
// of the program, before creating an Ice communicator or starting any thread.
Ice::CtrlCHandler ctrlCHandler;

ctrlCHandler.setCallback([communicator](int) { communicator->destroy(); });
// Create an Ice communicator to initialize the Ice runtime.
const Ice::CommunicatorHolder communicatorHolder{argc, argv, "config.pub"};
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator();

status = run(communicator, argc, argv);
}
catch (const std::exception& ex)
{
cerr << ex.what() << endl;
status = 1;
}

return status;
}

void
usage(const string& n)
{
cerr << "Usage: " << n << " [--datagram|--twoway|--oneway] [topic]" << endl;
}
// Parse command-line options.

int
run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
{
enum class Option : uint8_t
{
None,
Datagram,
Twoway,
Oneway
};

Option option = Option::None;
string topicName = "time";
int i;
Expand Down Expand Up @@ -114,16 +88,15 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
return 1;
}

auto manager = Ice::checkedCast<IceStorm::TopicManagerPrx>(communicator->propertyToProxy("TopicManager.Proxy"));
// Create the topic manager proxy.
auto manager = communicator->propertyToProxy<IceStorm::TopicManagerPrx>("TopicManager.Proxy");
if (!manager)
{
cerr << argv[0] << ": invalid proxy" << endl;
return 1;
}

//
// Retrieve the topic.
//
// Retrieve the topic from IceStorm.
optional<IceStorm::TopicPrx> topic;
try
{
Expand All @@ -142,10 +115,8 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
}
}

//
// Get the topic's publisher object, and create a Clock proxy with
// the mode specified as an argument of this application.
//
// Get the topic's publisher object, and create a Clock proxy with the mode specified as an argument of this
// application.
auto publisher = topic->getPublisher();
if (option == Option::Datagram)
{
Expand All @@ -160,27 +131,56 @@ run(const shared_ptr<Ice::Communicator>& communicator, int argc, char* argv[])
publisher = publisher->ice_oneway();
}

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

cout << "publishing tick events. Press ^C to terminate the application." << endl;
while (true)
{
try

promise<void> cancelPromise;

// Send a tick every second until cancelled in a background task.
auto task = std::async(
std::launch::async,
[cancelFuture = cancelPromise.get_future(), clock = std::move(clock)]()
{
auto now = chrono::system_clock::to_time_t(chrono::system_clock::now());
char timeString[100];
if (strftime(timeString, sizeof(timeString), "%x %X", localtime(&now)) == 0)
while (true)
{
timeString[0] = '\0';
auto now = chrono::system_clock::to_time_t(chrono::system_clock::now());
char timeString[100];
if (strftime(timeString, sizeof(timeString), "%x %X", localtime(&now)) == 0)
{
timeString[0] = '\0';
}

try
{
clock->tick(timeString);
}
catch (const Ice::CommunicatorDestroyedException&)
{
break; // done
}

// Sleep for one second or until canceled.
if (cancelFuture.wait_for(chrono::seconds(1)) == future_status::ready)
{
break; // done
}
}
clock->tick(timeString);
this_thread::sleep_for(chrono::seconds(1));
}
catch (const Ice::CommunicatorDestroyedException&)
{
break;
}
}
});

// Wait until the user presses Ctrl+C.
int signal = ctrlCHandler.wait();
cout << "Caught signal " << signal << ", exiting..." << endl;

// Cancel the sleep in the background task.
cancelPromise.set_value();

// Destroy the communicator in case a call to tick is taking a long time.
communicator->destroy();

// Wait for the background task to complete.
task.wait();

return 0;
}
Loading
Loading