Skip to content

Commit 8a65ec9

Browse files
New Ice/bidir demo for C++ (#295)
1 parent 11cf8a8 commit 8a65ec9

File tree

15 files changed

+266
-349
lines changed

15 files changed

+266
-349
lines changed

cpp/Ice/bidir/AlarmClock.ice

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#pragma once
4+
5+
module EarlyRiser
6+
{
7+
/// Indicates the button pressed when the alarm rang.
8+
enum ButtonPressed { Snooze, Stop }
9+
10+
/// Represents a simple alarm clock. It's the "callback" in this demo, and it's implemented by the client.
11+
interface AlarmClock
12+
{
13+
/// Rings the alarm clock.
14+
/// @param message The message to display.
15+
/// @return The button pressed by the user.
16+
ButtonPressed ring(string message);
17+
}
18+
19+
/// Represents the wake up service provided by the server.
20+
interface WakeUpService
21+
{
22+
/// Schedules a call to the caller's {@link AlarmClock::ring} at the specified time.
23+
/// @param timeStamp The time to ring the alarm clock. It's encoded as the number of ticks (100 nanoseconds)
24+
/// since January 1, 0001 00:00:00 UTC in the Gregorian calendar.
25+
void wakeMeUp(long timeStamp);
26+
}
27+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#include "BidirWakeUpService.h"
4+
5+
#include <algorithm>
6+
#include <iostream>
7+
8+
using namespace EarlyRiser;
9+
using namespace std;
10+
11+
namespace
12+
{
13+
// Converts a time stamp to a time point.
14+
chrono::system_clock::time_point toTimePoint(int64_t timeStamp)
15+
{
16+
const int daysBeforeEpoch = 719162;
17+
18+
chrono::microseconds timePointMicro{timeStamp / 10}; // timeStamp is in ticks (100 nanoseconds)
19+
return chrono::system_clock::time_point{timePointMicro - daysBeforeEpoch * 24h};
20+
}
21+
}
22+
23+
Server::BidirWakeUpService::~BidirWakeUpService()
24+
{
25+
// Waits for all outstanding tasks to complete.
26+
for (auto& task : _tasks)
27+
{
28+
task.wait();
29+
}
30+
}
31+
32+
void
33+
Server::BidirWakeUpService::wakeMeUp(int64_t timeStamp, const Ice::Current& current)
34+
{
35+
// With C++20, we'll be able to print the time point easily--but not with C++17.
36+
cout << "Dispatching wakeMeUp request { timeStamp = " << timeStamp << " ticks }" << endl;
37+
38+
chrono::system_clock::time_point timePoint = toTimePoint(timeStamp);
39+
40+
Ice::ConnectionPtr connection = current.con; // The connection from the client to the server.
41+
if (!connection)
42+
{
43+
// Should never happen, but in case it does, the Ice runtime will send an Ice::UnknownException to the client.
44+
throw std::invalid_argument{"BidirWakeUpService does not support collocated calls"};
45+
}
46+
47+
// Create a proxy to the client's alarm clock. This connection-bound proxy is called a "fixed proxy".
48+
auto alarmClock = connection->createProxy<AlarmClockPrx>(Ice::stringToIdentity("alarmClock"));
49+
50+
// Schedule a wake-up call in a background task.
51+
_tasks.emplace_back(std::async(
52+
std::launch::async,
53+
[alarmClock = std::move(alarmClock), timePoint]()
54+
{
55+
// Sleep until the specified time point.
56+
this_thread::sleep_until(timePoint);
57+
58+
// First ring.
59+
ButtonPressed buttonPressed = alarmClock->ring("It's time to wake up!");
60+
61+
// Keep ringing every 10 seconds until the user presses the stop button.
62+
while (buttonPressed == ButtonPressed::Snooze)
63+
{
64+
this_thread::sleep_for(10s);
65+
buttonPressed = alarmClock->ring("No more snoozing!");
66+
}
67+
}));
68+
69+
// We don't want the _tasks vector to grow forever so remove all completed tasks here, without waiting.
70+
// TODO: switch to std::erase_if when we can use C++20.
71+
_tasks.erase(
72+
std::remove_if(
73+
_tasks.begin(),
74+
_tasks.end(),
75+
[](const auto& task) { return task.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }),
76+
_tasks.end());
77+
}

cpp/Ice/bidir/BidirWakeUpService.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) ZeroC, Inc.
2+
3+
#ifndef BIDIR_WAKE_UP_SERVICE_H
4+
#define BIDIR_WAKE_UP_SERVICE_H
5+
6+
#include "AlarmClock.h"
7+
8+
#include <future>
9+
#include <vector>
10+
11+
namespace Server
12+
{
13+
/// BidirWakeUpService is an Ice servant that implements Slice interface WakeUpService.
14+
class BidirWakeUpService : public EarlyRiser::WakeUpService
15+
{
16+
public:
17+
// Waits for all outstanding tasks to complete.
18+
~BidirWakeUpService() override;
19+
20+
// Implements the pure virtual function in the base class (WakeUpService) generated by the Slice compiler.
21+
void wakeMeUp(std::int64_t timeStamp, const Ice::Current&) override;
22+
23+
private:
24+
std::vector<std::future<void>> _tasks;
25+
};
26+
}
27+
28+
#endif

cpp/Ice/bidir/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ project(bidir CXX)
44

55
include(../../cmake/common.cmake)
66

7-
add_executable(client Client.cpp Callback.ice)
7+
add_executable(client Client.cpp MockAlarmClock.h MockAlarmClock.cpp AlarmClock.ice)
88
slice2cpp_generate(client)
99
target_link_libraries(client Ice::Ice)
1010

11-
add_executable(server Server.cpp CallbackI.cpp CallbackI.h Callback.ice)
11+
add_executable(server Server.cpp BidirWakeUpService.h BidirWakeUpService.cpp AlarmClock.ice)
1212
slice2cpp_generate(server)
1313
target_link_libraries(server Ice::Ice)

cpp/Ice/bidir/Callback.ice

Lines changed: 0 additions & 16 deletions
This file was deleted.

cpp/Ice/bidir/CallbackI.cpp

Lines changed: 0 additions & 99 deletions
This file was deleted.

cpp/Ice/bidir/CallbackI.h

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)