Skip to content

Commit

Permalink
Updated class for sync mutex usage
Browse files Browse the repository at this point in the history
Signed-off-by: AssemblyJohn <[email protected]>
  • Loading branch information
AssemblyJohn committed Oct 21, 2024
1 parent 1e8c2bd commit 70d9f73
Showing 1 changed file with 74 additions and 67 deletions.
141 changes: 74 additions & 67 deletions include/everest/timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

#include <boost/asio.hpp>
#include <chrono>
#include <condition_variable>
#include <date/date.h>
#include <date/tz.h>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>

Expand All @@ -20,8 +20,8 @@ template <typename Type, bool Exists> struct OptionalTimerMember {

template <typename Type> struct OptionalTimerMember<Type, false> {};

template <template<typename> typename Guard, typename Mutex, bool Enabled> struct OptionalGuard {
OptionalGuard(OptionalTimerMember<Mutex, Enabled> &in_mutex) {
template <template <typename> typename Guard, typename Mutex, bool Enabled> struct OptionalGuard {
OptionalGuard(OptionalTimerMember<Mutex, Enabled>& in_mutex) {

Check notice on line 24 in include/everest/timer.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/everest/timer.hpp#L24

Struct 'OptionalGuard' has a constructor with 1 argument that is not explicit.
if constexpr (Enabled) {
guard.data = std::move(Guard<Mutex>(in_mutex.data));
}
Expand All @@ -31,12 +31,12 @@ template <template<typename> typename Guard, typename Mutex, bool Enabled> struc
};

// template <typename TimerClock = date::steady_clock> class Timer {
template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class Timer {
template <typename TimerClock = date::utc_clock, bool ThreadSafe = false, bool SharedContext = false> class Timer {
private:
boost::asio::basic_waitable_timer<TimerClock>* timer = nullptr;
std::unique_ptr<boost::asio::basic_waitable_timer<TimerClock>> timer = nullptr;
std::function<void()> callback;
std::function<void(const boost::system::error_code& e)> callback_wrapper;
std::chrono::nanoseconds interval_nanoseconds;
std::chrono::nanoseconds interval_nanoseconds;
boost::asio::io_context io_context;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work;
std::thread* timer_thread = nullptr;
Expand All @@ -47,18 +47,18 @@ template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class
public:
/// This timer will initialize a boost::asio::io_context
explicit Timer() : work(boost::asio::make_work_guard(this->io_context)) {
this->timer = new boost::asio::basic_waitable_timer<TimerClock>(this->io_context);
this->timer = std::make_unique<boost::asio::basic_waitable_timer<TimerClock>>(this->io_context);
this->timer_thread = new std::thread([this]() { this->io_context.run(); });
}

explicit Timer(const std::function<void()>& callback) : work(boost::asio::make_work_guard(this->io_context)) {
this->timer = new boost::asio::basic_waitable_timer<TimerClock>(this->io_context);
this->timer = std::make_unique<boost::asio::basic_waitable_timer<TimerClock>>(this->io_context);
this->timer_thread = new std::thread([this]() { this->io_context.run(); });
this->callback = callback;
}

explicit Timer(boost::asio::io_context* io_context) : work(boost::asio::make_work_guard(*io_context)) {
this->timer = new boost::asio::basic_waitable_timer<TimerClock>(*io_context);
this->timer = std::make_unique<boost::asio::basic_waitable_timer<TimerClock>>(*io_context);
}

explicit Timer(boost::asio::io_context* io_context, const std::function<void()>& callback) :
Expand All @@ -85,24 +85,74 @@ template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class
/// Executes the given callback at the given timepoint
template <class Clock, class Duration = typename Clock::duration>
void at(const std::function<void()>& callback, const std::chrono::time_point<Clock, Duration>& time_point) {
if constexpr(ThreadSafe) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);
this->stop();
this->callback = callback;
} else {
this->stop();
this->callback = callback;
}
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

Check notice on line 88 in include/everest/timer.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/everest/timer.hpp#L88

Variable 'optional_guard' is assigned a value that is never used.

this->stop_internal();
this->callback = callback;

this->at(time_point);
this->at_internal(time_point);
}

/// Executes the at the given timepoint
template <class Clock, class Duration = typename Clock::duration>
void at(const std::chrono::time_point<Clock, Duration>& time_point) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->stop();
at_internal<Clock, Duration>(time_point);
}

/// Execute the given callback peridically from now in the given interval
template <class Rep, class Period>
void interval(const std::function<void()>& callback, const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->stop_internal();
this->callback = callback;

this->interval_internal(interval);
}

/// Execute peridically from now in the given interval
template <class Rep, class Period> void interval(const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->interval_internal(interval);
}

// Execute the given callback once after the given interval
template <class Rep, class Period>
void timeout(const std::function<void()>& callback, const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->stop_internal();
this->callback = callback;

this->timeout_internal(interval);
}

// Execute the given callback once after the given interval
template <class Rep, class Period> void timeout(const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->timeout_internal(interval);
}

/// Stop timer from excuting its callback
void stop() {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

stop_internal();
}

bool is_running() {
return running;
}

private:
/// Executes the at the given timepoint
template <class Clock, class Duration = typename Clock::duration>
void at_internal(const std::chrono::time_point<Clock, Duration>& time_point) {
this->stop_internal();

if (this->callback == nullptr) {
return;
Expand All @@ -124,28 +174,9 @@ template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class
}
}

/// Execute the given callback peridically from now in the given interval
template <class Rep, class Period>
void interval(const std::function<void()>& callback, const std::chrono::duration<Rep, Period>& interval) {
if constexpr(ThreadSafe) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->stop();
this->callback = callback;
} else {
this->stop();
this->callback = callback;
}


this->interval(interval);
}
template <class Rep, class Period> void interval_internal(const std::chrono::duration<Rep, Period>& interval) {
this->stop_internal();

/// Execute peridically from now in the given interval
template <class Rep, class Period> void interval(const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

this->stop();
this->interval_nanoseconds = interval;
if (interval_nanoseconds == std::chrono::nanoseconds(0)) {
return;
Expand Down Expand Up @@ -176,25 +207,8 @@ template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class
}
}

// Execute the given callback once after the given interval
template <class Rep, class Period>
void timeout(const std::function<void()>& callback, const std::chrono::duration<Rep, Period>& interval) {
if constexpr (ThreadSafe) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);
this->stop();
this->callback = callback;
} else {
this->stop();
this->callback = callback;
}

this->timeout(interval);
}

// Execute the given callback once after the given interval
template <class Rep, class Period> void timeout(const std::chrono::duration<Rep, Period>& interval) {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);
this->stop();
template <class Rep, class Period> void timeout_internal(const std::chrono::duration<Rep, Period>& interval) {
this->stop_internal();

if (this->callback == nullptr) {
return;
Expand All @@ -217,21 +231,14 @@ template <typename TimerClock = date::utc_clock, bool ThreadSafe = false> class
}
}

/// Stop timer from excuting its callback
void stop() {
OptionalGuard<std::unique_lock, std::mutex, ThreadSafe> optional_guard(this->mutex);

void stop_internal() {
if (this->timer != nullptr) {
// asio based timer
this->timer->cancel();
}

running = false;
}

bool is_running() {
return running;
}
};

using SteadyTimer = Timer<date::utc_clock>;
Expand Down

0 comments on commit 70d9f73

Please sign in to comment.