-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
11cf8a8
commit 8a65ec9
Showing
15 changed files
with
266 additions
and
349 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#pragma once | ||
|
||
module EarlyRiser | ||
{ | ||
/// Indicates the button pressed when the alarm rang. | ||
enum ButtonPressed { Snooze, Stop } | ||
|
||
/// Represents a simple alarm clock. It's the "callback" in this demo, and it's implemented by the client. | ||
interface AlarmClock | ||
{ | ||
/// Rings the alarm clock. | ||
/// @param message The message to display. | ||
/// @return The button pressed by the user. | ||
ButtonPressed ring(string message); | ||
} | ||
|
||
/// Represents the wake up service provided by the server. | ||
interface WakeUpService | ||
{ | ||
/// Schedules a call to the caller's {@link AlarmClock::ring} at the specified time. | ||
/// @param timeStamp The time to ring the alarm clock. It's encoded as the number of ticks (100 nanoseconds) | ||
/// since January 1, 0001 00:00:00 UTC in the Gregorian calendar. | ||
void wakeMeUp(long timeStamp); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#include "BidirWakeUpService.h" | ||
|
||
#include <algorithm> | ||
#include <iostream> | ||
|
||
using namespace EarlyRiser; | ||
using namespace std; | ||
|
||
namespace | ||
{ | ||
// Converts a time stamp to a time point. | ||
chrono::system_clock::time_point toTimePoint(int64_t timeStamp) | ||
{ | ||
const int daysBeforeEpoch = 719162; | ||
|
||
chrono::microseconds timePointMicro{timeStamp / 10}; // timeStamp is in ticks (100 nanoseconds) | ||
return chrono::system_clock::time_point{timePointMicro - daysBeforeEpoch * 24h}; | ||
} | ||
} | ||
|
||
Server::BidirWakeUpService::~BidirWakeUpService() | ||
{ | ||
// Waits for all outstanding tasks to complete. | ||
for (auto& task : _tasks) | ||
{ | ||
task.wait(); | ||
} | ||
} | ||
|
||
void | ||
Server::BidirWakeUpService::wakeMeUp(int64_t timeStamp, const Ice::Current& current) | ||
{ | ||
// With C++20, we'll be able to print the time point easily--but not with C++17. | ||
cout << "Dispatching wakeMeUp request { timeStamp = " << timeStamp << " ticks }" << endl; | ||
|
||
chrono::system_clock::time_point timePoint = toTimePoint(timeStamp); | ||
|
||
Ice::ConnectionPtr connection = current.con; // The connection from the client to the server. | ||
if (!connection) | ||
{ | ||
// Should never happen, but in case it does, the Ice runtime will send an Ice::UnknownException to the client. | ||
throw std::invalid_argument{"BidirWakeUpService does not support collocated calls"}; | ||
} | ||
|
||
// Create a proxy to the client's alarm clock. This connection-bound proxy is called a "fixed proxy". | ||
auto alarmClock = connection->createProxy<AlarmClockPrx>(Ice::stringToIdentity("alarmClock")); | ||
|
||
// Schedule a wake-up call in a background task. | ||
_tasks.emplace_back(std::async( | ||
std::launch::async, | ||
[alarmClock = std::move(alarmClock), timePoint]() | ||
{ | ||
// Sleep until the specified time point. | ||
this_thread::sleep_until(timePoint); | ||
|
||
// First ring. | ||
ButtonPressed buttonPressed = alarmClock->ring("It's time to wake up!"); | ||
|
||
// Keep ringing every 10 seconds until the user presses the stop button. | ||
while (buttonPressed == ButtonPressed::Snooze) | ||
{ | ||
this_thread::sleep_for(10s); | ||
buttonPressed = alarmClock->ring("No more snoozing!"); | ||
} | ||
})); | ||
|
||
// We don't want the _tasks vector to grow forever so remove all completed tasks here, without waiting. | ||
// TODO: switch to std::erase_if when we can use C++20. | ||
_tasks.erase( | ||
std::remove_if( | ||
_tasks.begin(), | ||
_tasks.end(), | ||
[](const auto& task) { return task.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }), | ||
_tasks.end()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#ifndef BIDIR_WAKE_UP_SERVICE_H | ||
#define BIDIR_WAKE_UP_SERVICE_H | ||
|
||
#include "AlarmClock.h" | ||
|
||
#include <future> | ||
#include <vector> | ||
|
||
namespace Server | ||
{ | ||
/// BidirWakeUpService is an Ice servant that implements Slice interface WakeUpService. | ||
class BidirWakeUpService : public EarlyRiser::WakeUpService | ||
{ | ||
public: | ||
// Waits for all outstanding tasks to complete. | ||
~BidirWakeUpService() override; | ||
|
||
// Implements the pure virtual function in the base class (WakeUpService) generated by the Slice compiler. | ||
void wakeMeUp(std::int64_t timeStamp, const Ice::Current&) override; | ||
|
||
private: | ||
std::vector<std::future<void>> _tasks; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.