Use callback function instead of class

This commit is contained in:
badaix 2025-02-16 22:04:33 +01:00 committed by Johannes Pohl
parent efd050a716
commit f0985cbce4
4 changed files with 40 additions and 33 deletions

View file

@ -114,8 +114,8 @@ void ProcessStream::connect()
on_connect(); on_connect();
if (wd_timeout_sec_ > 0) if (wd_timeout_sec_ > 0)
{ {
watchdog_ = make_unique<Watchdog>(strand_, this); watchdog_ = make_unique<Watchdog>(strand_);
watchdog_->start(std::chrono::seconds(wd_timeout_sec_)); watchdog_->start(std::chrono::seconds(wd_timeout_sec_), [this](std::chrono::milliseconds ms) { onTimeout(ms); });
} }
else else
{ {
@ -171,7 +171,7 @@ void ProcessStream::stderrReadLine()
} }
void ProcessStream::onTimeout(const Watchdog& /*watchdog*/, std::chrono::milliseconds ms) void ProcessStream::onTimeout(std::chrono::milliseconds ms)
{ {
LOG(ERROR, LOG_TAG) << "Watchdog timeout: " << ms.count() / 1000 << "s\n"; LOG(ERROR, LOG_TAG) << "Watchdog timeout: " << ms.count() / 1000 << "s\n";
if (process_) if (process_)

View file

@ -1,6 +1,6 @@
/*** /***
This file is part of snapcast This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -42,38 +42,43 @@ using boost::asio::posix::stream_descriptor;
* Implements EncoderListener to get the encoded data. * Implements EncoderListener to get the encoded data.
* Data is passed to the PcmStream::Listener * Data is passed to the PcmStream::Listener
*/ */
class ProcessStream : public AsioStream<stream_descriptor>, public WatchdogListener class ProcessStream : public AsioStream<stream_descriptor>
{ {
public: public:
/// ctor. Encoded PCM data is passed to the PipeListener /// c'tor. Encoded PCM data is passed to the PipeListener
ProcessStream(PcmStream::Listener* pcmListener, boost::asio::io_context& ioc, const ServerSettings& server_settings, const StreamUri& uri); ProcessStream(PcmStream::Listener* pcmListener, boost::asio::io_context& ioc, const ServerSettings& server_settings, const StreamUri& uri);
/// d'tor
~ProcessStream() override = default; ~ProcessStream() override = default;
protected: protected:
void connect() override; void connect() override;
void disconnect() override; void disconnect() override;
std::string exe_; std::string exe_; ///< filename of the process
std::string path_; std::string path_; ///< base path of the provess
std::string params_; std::string params_; ///< parameters for the process
bp::pipe pipe_stdout_; bp::pipe pipe_stdout_; ///< stdout of the process
bp::pipe pipe_stderr_; bp::pipe pipe_stderr_; ///< stderr of the process
bp::child process_; bp::child process_; ///< the process
bool logStderr_; bool logStderr_; ///< log stderr to log?
boost::asio::streambuf streambuf_stderr_; boost::asio::streambuf streambuf_stderr_; ///< stderr read buffer
std::unique_ptr<stream_descriptor> stream_stderr_; std::unique_ptr<stream_descriptor> stream_stderr_; ///< stderr stream
// void worker() override; /// Read async from stderr
virtual void stderrReadLine(); virtual void stderrReadLine();
/// Called for a line read from stderr
virtual void onStderrMsg(const std::string& line); virtual void onStderrMsg(const std::string& line);
/// Try to find exe and base path, throw on error
virtual void initExeAndPath(const std::string& filename); virtual void initExeAndPath(const std::string& filename);
/// @return the executables complete path to @p filename
std::string findExe(const std::string& filename) const; std::string findExe(const std::string& filename) const;
size_t wd_timeout_sec_; size_t wd_timeout_sec_; ///< Watchdog timeout for arrival of new log lines
std::unique_ptr<Watchdog> watchdog_; std::unique_ptr<Watchdog> watchdog_; ///< the watchdog
void onTimeout(const Watchdog& watchdog, std::chrono::milliseconds ms) override; /// called on wd timeout, kills the process
void onTimeout(std::chrono::milliseconds ms);
}; };
} // namespace streamreader } // namespace streamreader

View file

@ -36,7 +36,7 @@ using namespace std;
namespace streamreader namespace streamreader
{ {
Watchdog::Watchdog(const boost::asio::any_io_executor& executor, WatchdogListener* listener) : timer_(executor), listener_(listener) Watchdog::Watchdog(const boost::asio::any_io_executor& executor) : timer_(executor)
{ {
} }
@ -47,9 +47,10 @@ Watchdog::~Watchdog()
} }
void Watchdog::start(const std::chrono::milliseconds& timeout) void Watchdog::start(const std::chrono::milliseconds& timeout, TimeoutHandler&& handler)
{ {
LOG(INFO, LOG_TAG) << "Starting watchdog, timeout: " << std::chrono::duration_cast<std::chrono::seconds>(timeout).count() << "s\n"; LOG(INFO, LOG_TAG) << "Starting watchdog, timeout: " << std::chrono::duration_cast<std::chrono::seconds>(timeout).count() << "s\n";
handler_ = std::move(handler);
timeout_ms_ = timeout; timeout_ms_ = timeout;
trigger(); trigger();
} }
@ -70,7 +71,8 @@ void Watchdog::trigger()
if (!ec) if (!ec)
{ {
LOG(INFO, LOG_TAG) << "Timed out: " << std::chrono::duration_cast<std::chrono::seconds>(timeout_ms_).count() << "s\n"; LOG(INFO, LOG_TAG) << "Timed out: " << std::chrono::duration_cast<std::chrono::seconds>(timeout_ms_).count() << "s\n";
listener_->onTimeout(*this, timeout_ms_); if (handler_)
handler_(timeout_ms_);
} }
}); });
} }

View file

@ -1,6 +1,6 @@
/*** /***
This file is part of snapcast This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -32,27 +32,27 @@ namespace streamreader
class Watchdog; class Watchdog;
class WatchdogListener
{
public:
virtual void onTimeout(const Watchdog& watchdog, std::chrono::milliseconds ms) = 0;
};
/// Watchdog /// Watchdog
class Watchdog class Watchdog
{ {
public: public:
Watchdog(const boost::asio::any_io_executor& executor, WatchdogListener* listener = nullptr); using TimeoutHandler = std::function<void(std::chrono::milliseconds ms)>;
/// c'tor
explicit Watchdog(const boost::asio::any_io_executor& executor);//, WatchdogListener* listener = nullptr);
/// d'tor
virtual ~Watchdog(); virtual ~Watchdog();
void start(const std::chrono::milliseconds& timeout); /// start the watchdog, call @p handler on @p timeout
void start(const std::chrono::milliseconds& timeout, TimeoutHandler&& handler);
/// stop the watchdog
void stop(); void stop();
/// trigger the watchdog (reset timeout)
void trigger(); void trigger();
private: private:
boost::asio::steady_timer timer_; boost::asio::steady_timer timer_;
WatchdogListener* listener_; TimeoutHandler handler_;
std::chrono::milliseconds timeout_ms_; std::chrono::milliseconds timeout_ms_;
}; };