Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
13 changes: 13 additions & 0 deletions cpp/IceStorm/clock/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.16)

project(clock CXX)

include(../../cmake/common.cmake)

add_executable(publisher Publisher.cpp Clock.ice)
slice2cpp_generate(publisher)
target_link_libraries(publisher Ice::Ice)

add_executable(subscriber Subscriber.cpp Clock.ice)
slice2cpp_generate(subscriber)
target_link_libraries(subscriber Ice::Ice)
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);
}
}
118 changes: 53 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;
// 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;

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.setCallback([communicator](int) { communicator->destroy(); });

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

return status;
}
// Create an Ice communicator to initialize the Ice runtime.
const Ice::CommunicatorHolder communicatorHolder{argc, argv, "config.pub"};
const Ice::CommunicatorPtr& communicator = communicatorHolder.communicator();

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,44 @@ 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

// Send a tick every second until cancelled in a background task.
auto future = std::async(
std::launch::async,
[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';
try
{
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';
}
clock->tick(timeString);
this_thread::sleep_for(chrono::seconds(1));
}
catch (const Ice::CommunicatorDestroyedException&)
{
break; // done
}
}
clock->tick(timeString);
this_thread::sleep_for(chrono::seconds(1));
}
catch (const Ice::CommunicatorDestroyedException&)
{
break;
}
}
});

// Wait until the user presses Ctrl+C.
ctrlCHandler.wait();

// Destroy the communicator; the next call to tick will throw CommunicatorDestroyedException.
communicator->destroy();

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

return 0;
}
Loading