Skip to content

Commit

Permalink
Another try to improve Retry
Browse files Browse the repository at this point in the history
  • Loading branch information
kuznetsss committed Dec 20, 2024
1 parent 285d4e6 commit 0cf9578
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 31 deletions.
13 changes: 9 additions & 4 deletions src/util/Repeat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@

namespace util {

Repeat::~Repeat()
{
*stopping_ = true;
std::cout << "~" << std::endl;
}

void
Repeat::stop()
{
if (control_->stopping)
if (*stopping_)
return;
control_->stopping = true;
control_->timer.cancel();
control_->semaphore.acquire();
*stopping_ = true;
timer_.cancel();
}

} // namespace util
61 changes: 34 additions & 27 deletions src/util/Repeat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <chrono>
#include <concepts>
#include <memory>
#include <semaphore>
#include <utility>

namespace util {

Expand All @@ -38,17 +38,8 @@ namespace util {
* @note io_context must be stopped before the Repeat object is destroyed. Otherwise it is undefined behavior
*/
class Repeat {
struct Control {
boost::asio::steady_timer timer;
std::atomic_bool stopping{true};
std::binary_semaphore semaphore{0};

Control(auto& ctx) : timer(ctx)
{
}
};

std::unique_ptr<Control> control_;
boost::asio::steady_timer timer_;
std::shared_ptr<std::atomic_bool> stopping_ = std::make_shared<std::atomic_bool>(true);

public:
/**
Expand All @@ -57,10 +48,12 @@ class Repeat {
*
* @param ctx The io_context-like object to use
*/
Repeat(auto& ctx) : control_(std::make_unique<Control>(ctx))
Repeat(auto& ctx) : timer_(ctx)
{
}

~Repeat();

Repeat(Repeat const&) = delete;
Repeat&
operator=(Repeat const&) = delete;
Expand All @@ -87,26 +80,40 @@ class Repeat {
void
start(std::chrono::steady_clock::duration interval, Action&& action)
{
ASSERT(control_->stopping, "Should be stopped before starting");
control_->stopping = false;
startImpl(interval, std::forward<Action>(action));
ASSERT(*stopping_, "Should be stopped before starting");
*stopping_ = false;
startImpl(interval, std::forward<Action>(action), stopping_, timer_);
}

private:
template <std::invocable Action>
void
startImpl(std::chrono::steady_clock::duration interval, Action&& action)
static void
startImpl(
std::chrono::steady_clock::duration interval,
Action&& action,
std::shared_ptr<std::atomic_bool> stopping,
boost::asio::steady_timer& timer
)
{
control_->timer.expires_after(interval);
control_->timer.async_wait([this, interval, action = std::forward<Action>(action)](auto const& ec) mutable {
if (ec or control_->stopping) {
control_->semaphore.release();
return;
}
action();
if (*stopping) {
std::cout << "Exit 1" << std::endl;
return;
}

startImpl(interval, std::forward<Action>(action));
});
timer.expires_after(interval);
timer.async_wait(
[interval, action = std::forward<Action>(action), &timer, stopping = std::move(stopping)](auto&&) mutable {
if (*stopping) {
std::cout << "Exit 2" << std::endl;
return;
}
std::cout << "action()" << std::endl;
action();

std::cout << "restart" << std::endl;
startImpl(interval, std::forward<Action>(action), std::move(stopping), timer);
}
);
}
};

Expand Down

0 comments on commit 0cf9578

Please sign in to comment.