Merge branch 'master' of https://code.uocat.com/tqcq/sled
Some checks failed
linux-x64-gcc / linux-gcc (Debug) (push) Failing after 1m16s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Failing after 1m28s
linux-arm-gcc / linux-gcc-armhf (push) Failing after 1m30s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Failing after 1m55s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Failing after 2m16s
linux-x64-gcc / linux-gcc (Release) (push) Failing after 2m16s

This commit is contained in:
tqcq 2024-05-01 06:48:49 +00:00
commit 4fe83af09d
3 changed files with 81 additions and 26 deletions

View File

@ -8,6 +8,7 @@
#define SLED_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H #define SLED_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H
#pragma once #pragma once
#include "sled/meta/type_traits.h"
#include "sled/ref_counted_base.h" #include "sled/ref_counted_base.h"
#include "sled/scoped_refptr.h" #include "sled/scoped_refptr.h"
#include "sled/synchronization/sequence_checker.h" #include "sled/synchronization/sequence_checker.h"
@ -53,11 +54,22 @@ private:
scoped_refptr<PendingTaskSafetyFlag> flag_; scoped_refptr<PendingTaskSafetyFlag> flag_;
}; };
inline std::function<void()> template<typename F, typename... Args, typename = EnableIfT<!std::is_void<InvokeResultT<F, Args...>>::value>>
SafeTask(scoped_refptr<PendingTaskSafetyFlag> flag, std::function<void()> task) std::function<InvokeResultT<F, Args...>(Args &&...)>
SafeTask(scoped_refptr<PendingTaskSafetyFlag> flag, F &&f)
{ {
return [flag, task]() mutable { return [flag, f](Args &&...args) mutable -> InvokeResultT<F, Args...> {
if (flag->alive()) { std::move(task)(); } if (flag->alive()) { return f(std::forward<Args>(args)...); }
return {};
};
}
template<typename F, typename... Args, typename = EnableIfT<std::is_void<InvokeResultT<F, Args...>>::value>>
std::function<void(Args &&...)>
SafeTask(scoped_refptr<PendingTaskSafetyFlag> flag, F &&f)
{
return [flag, f](Args &&...args) mutable -> void {
if (flag->alive()) { f(std::forward<Args>(args)...); }
}; };
} }

View File

@ -1,4 +1,5 @@
#include "sled/timer/timer.h" #include "sled/timer/timer.h"
#include "sled/log/log.h"
namespace sled { namespace sled {
namespace { namespace {
@ -9,6 +10,22 @@ MakeTimeoutId(TimerID timer_id, TimerGeneration generation)
} }
}// namespace }// namespace
TimerThreadDeleter::TimerThreadDeleter(TaskQueueBase *owner) : owner_(owner) {}
void
TimerThreadDeleter::operator()(Timer *timer)
{
if (!timer) { return; }
if (owner_) {
owner_->PostTask([timer]() {
timer->Stop();
delete timer;
});
} else {
delete timer;
}
}
Timer::Timer(TimerID id, Timer::Timer(TimerID id,
const std::string &name, const std::string &name,
OnExpired on_expired, OnExpired on_expired,
@ -47,12 +64,26 @@ Timer::Stop()
{ {
if (is_running()) { if (is_running()) {
timeout_->Stop(); timeout_->Stop();
generation_ = TimerGeneration(generation_ + 1); generation_ = TimerGeneration(generation_ + 1);
expiration_count_ = 0; expiration_count_ = 0;
is_running_ = false; is_running_ = false;
} }
} }
void
Timer::Start(TaskQueueBase *owner)
{
SLED_ASSERT(owner != nullptr, "owner must not be nullptr");
owner->BlockingCall([this]() { Start(); });
}
void
Timer::Stop(TaskQueueBase *owner)
{
SLED_ASSERT(owner != nullptr, "owner must not be nullptr");
owner->BlockingCall([this]() { Stop(); });
}
void void
Timer::Trigger(TimerGeneration generation) Timer::Trigger(TimerGeneration generation)
{ {
@ -81,23 +112,26 @@ Timer::Trigger(TimerGeneration generation)
std::unique_ptr<Timer> std::unique_ptr<Timer>
TimerManager::CreateTimer(const std::string &name, Timer::OnExpired on_expired) TimerManager::CreateTimer(const std::string &name, Timer::OnExpired on_expired)
{ {
next_id_ = TimerID(next_id_ + 1); next_id_ = TimerID(next_id_ + 1);
TimerID id = next_id_; TimerID id = next_id_;
std::unique_ptr<Timeout> timeout = timeout_creator_(sled::TaskQueueBase::DelayPrecision::kHigh); std::unique_ptr<Timeout> timeout = timeout_creator_(sled::TaskQueueBase::DelayPrecision::kHigh);
auto timer = std::unique_ptr<Timer>(new Timer( auto timer = std::unique_ptr<Timer>(new Timer(
id, name, std::move(on_expired), id,
/* ungrgister_handler=*/[this, id]() { timers_.erase(id); }, std::move(timeout))); name,
timers_[id] = timer.get(); std::move(on_expired),
/* ungrgister_handler=*/[this, id]() { timers_.erase(id); },
std::move(timeout)));
timers_[id] = timer.get();
return timer; return timer;
} }
void void
TimerManager::HandleTimeout(TimeoutID id) TimerManager::HandleTimeout(TimeoutID id)
{ {
TimerID timer_id = id >> 32; TimerID timer_id = id >> 32;
TimerGeneration generation = id & 0xffffffff; TimerGeneration generation = id & 0xffffffff;
auto it = timers_.find(timer_id); auto it = timers_.find(timer_id);
if (it != timers_.end()) { it->second->Trigger(generation); } if (it != timers_.end()) { it->second->Trigger(generation); }
} }
}// namespace sled }// namespace sled

View File

@ -13,18 +13,31 @@ namespace sled {
typedef uint64_t TimerID; typedef uint64_t TimerID;
typedef uint32_t TimerGeneration; typedef uint32_t TimerGeneration;
class Timer;
struct TimerThreadDeleter {
TimerThreadDeleter(TaskQueueBase *owner);
inline void operator()(Timer *timer);
private:
TaskQueueBase *owner_;
};
class Timer { class Timer {
public: public:
using OnExpired = std::function<sled::optional<DurationMs>()>; using OnExpired = std::function<sled::optional<DurationMs>()>;
Timer(const Timer &) = delete; Timer(const Timer &) = delete;
Timer &operator=(const Timer &) = delete; Timer &operator=(const Timer &) = delete;
~Timer(); ~Timer();
void Start(); void Start();
void Stop(); void Stop();
void Start(TaskQueueBase *owner);
void Stop(TaskQueueBase *owner);
void set_duration(DurationMs duration) { duration_ = duration; } void set_duration(DurationMs duration) { duration_ = duration; }
const DurationMs &duration() const { return duration_; } const DurationMs duration() const { return duration_; }
int expiration_count() const { return expiration_count_; } int expiration_count() const { return expiration_count_; }
@ -46,24 +59,20 @@ private:
const UnregisterHandler unregister_handler_; const UnregisterHandler unregister_handler_;
std::unique_ptr<Timeout> timeout_; std::unique_ptr<Timeout> timeout_;
DurationMs duration_; std::atomic<DurationMs> duration_;
TimerGeneration generation_ = TimerGeneration(0); TimerGeneration generation_ = TimerGeneration(0);
bool is_running_ = false; bool is_running_ = false;
int expiration_count_ = 0; int expiration_count_ = 0;
}; };
class TimerManager { class TimerManager {
using TimeoutCreator = std::function<std::unique_ptr<Timeout>( using TimeoutCreator = std::function<std::unique_ptr<Timeout>(sled::TaskQueueBase::DelayPrecision)>;
sled::TaskQueueBase::DelayPrecision)>;
public: public:
explicit TimerManager(TimeoutCreator timeout_creator) explicit TimerManager(TimeoutCreator timeout_creator) : timeout_creator_(timeout_creator) {}
: timeout_creator_(timeout_creator)
{}
std::unique_ptr<Timer> CreateTimer(const std::string &name, std::unique_ptr<Timer> CreateTimer(const std::string &name, Timer::OnExpired on_expired);
Timer::OnExpired on_expired);
void HandleTimeout(TimeoutID timeout_id); void HandleTimeout(TimeoutID timeout_id);
private: private: