Added ^C handling to some examples for clean exits.

This commit is contained in:
fpagliughi 2024-07-05 20:59:19 -04:00
parent 33d219a2a3
commit 0bf6394fb3
3 changed files with 51 additions and 9 deletions

View File

@ -27,6 +27,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- The `properties` list implements a const iterator
- Added a `to_string()` and `operator<<()` for reason codes.
- Cleaned up and fixed a number of example apps.
- Most apps no except server URI from the command line
- 'data_publish' example uses C++17 std::filesystem for creating a file-based encrypted persistence for messages.
- Reorganized the source repository
- Completely reformat the sources and added a .clang-format file (a project master and a slightly-different one for headers).
- Added GitHub CI Action, removing legacy Travis and Appveyor files

View File

@ -49,6 +49,8 @@
#include <iostream>
#include <string>
#include <thread> // For sleep
#include <atomic>
#include <csignal>
#include "mqtt/async_client.h"
@ -69,6 +71,14 @@ const int DELTA_MS = 100;
// How many to buffer while off-line
const int MAX_BUFFERED_MESSAGES = 1200;
// Atomic flag to tell the main loop to exit.
atomic<bool> quit{false};
// Handler for ^C (SIGINT)
void ctrlc_handler(int) {
quit = true;
}
// --------------------------------------------------------------------------
// Gets the current time as the number of milliseconds since the epoch:
// like a time_t with ms resolution.
@ -130,14 +140,17 @@ int main(int argc, char* argv[])
auto top = mqtt::topic(cli, "data/time", QOS);
cout << "Publishing data..." << endl;
// Install a ^C handler for user to signal when to exit
signal(SIGINT, ctrlc_handler);
// Sync clock to start of delta period
while (timestamp() % DELTA_MS != 0)
;
uint64_t t = timestamp(), tlast = t, tstart = t;
top.publish(to_string(t));
while (true) {
while (!quit) {
this_thread::sleep_for(SAMPLE_PERIOD);
t = timestamp();

View File

@ -52,6 +52,9 @@
#include <thread>
#include <filesystem>
#include <fstream>
#include <csignal>
#include <mutex>
#include <condition_variable>
#include "mqtt/async_client.h"
@ -77,6 +80,20 @@ const fs::path PERSIST_DIR{"persist"};
// A key for encoding the persistence data
const string PERSIST_KEY{"elephant"};
// Condition variable & flag to tell the main loop to exit.
std::condition_variable cv;
std::mutex mtx;
bool quit{false};
// Handler for ^C (SIGINT)
void ctrlc_handler(int) {
{
lock_guard<mutex> lk(mtx);
quit = true;
}
cv.notify_one();
}
/////////////////////////////////////////////////////////////////////////////
// Example of user-based file persistence with a simple XOR encoding scheme.
@ -108,7 +125,7 @@ class encoded_file_persistence : virtual public mqtt::iclient_persistence
}
// Gets the persistence file name for the supplied key.
fs::path path_name(const string& key) const { return dir_ /key; }
fs::path path_name(const string& key) const { return dir_ / key; }
public:
// Create the persistence object with the specified encoding key
@ -138,7 +155,10 @@ public:
// Close the persistent store that was previously opened.
// Remove the persistence directory, if it's empty.
void close() override { fs::remove(dir_); }
void close() override {
fs::remove(dir_);
fs::remove(dir_.parent_path());
}
// Clears persistence, so that it no longer contains any persisted data.
// Just remove all the files from the persistence directory.
@ -271,12 +291,18 @@ int main(int argc, char* argv[])
char tmbuf[32];
unsigned nsample = 0;
// The time at which to reads the next sample, starting now
auto tm = steady_clock::now();
// Install a ^C handler for user to signal when to exit
signal(SIGINT, ctrlc_handler);
while (true) {
// Pace the samples to the desired rate
this_thread::sleep_until(tm);
// The steady time at which to read the next sample
auto tm = steady_clock::now() + 250ms;
// Pace the sampling by letting the condition variable time out
// periodically. When 'cv' is signaled, it's time to quit.
unique_lock lk(mtx);
while (!cv.wait_until(lk, tm, []{ return quit; })) {
lk.unlock();
// Get a timestamp and format as a string
time_t t = system_clock::to_time_t(system_clock::now());
@ -293,6 +319,7 @@ int main(int argc, char* argv[])
top.publish(std::move(payload));
tm += PERIOD;
lk.lock();
}
// Disconnect