sled/src/sled/task_queue/pending_task_safety_flag.h
2024-05-01 14:27:02 +08:00

79 lines
2.3 KiB
C++

/**
* @file : pending_task_safety_flag
* @created : Wednesday Feb 14, 2024 17:55:39 CST
* @license : MIT
**/
#ifndef SLED_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H
#define SLED_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H
#pragma once
#include "sled/meta/type_traits.h"
#include "sled/ref_counted_base.h"
#include "sled/scoped_refptr.h"
#include "sled/synchronization/sequence_checker.h"
#include <functional>
namespace sled {
class PendingTaskSafetyFlag final : public sled::RefCountedNonVirtual<PendingTaskSafetyFlag> {
public:
static sled::scoped_refptr<PendingTaskSafetyFlag> Create();
static sled::scoped_refptr<PendingTaskSafetyFlag> CreateDetached();
static sled::scoped_refptr<PendingTaskSafetyFlag> CreateDetachedInactive();
~PendingTaskSafetyFlag() = default;
void SetNotAlive();
void SetAlive();
bool alive() const;
protected:
explicit PendingTaskSafetyFlag(bool alive) : alive_(alive) {}
private:
static sled::scoped_refptr<PendingTaskSafetyFlag> CreateInternal(bool alive);
bool alive_ = true;
SequenceChecker main_sequence_;
};
class ScopedTaskSafety final {
public:
ScopedTaskSafety() = default;
explicit ScopedTaskSafety(scoped_refptr<PendingTaskSafetyFlag> flag) : flag_(std::move(flag)) {}
~ScopedTaskSafety() { flag_->SetNotAlive(); }
void reset(scoped_refptr<PendingTaskSafetyFlag> new_flag = PendingTaskSafetyFlag::Create())
{
flag_->SetNotAlive();
flag_ = std::move(new_flag);
}
private:
scoped_refptr<PendingTaskSafetyFlag> flag_;
};
template<typename F, typename... Args, typename = EnableIfT<!std::is_void<InvokeResultT<F, Args...>>::value>>
std::function<InvokeResultT<F, Args...>(Args &&...)>
SafeTask(scoped_refptr<PendingTaskSafetyFlag> flag, F &&f)
{
return [flag, f](Args &&...args) mutable -> InvokeResultT<F, Args...> {
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)...); }
};
}
}// namespace sled
#endif// SLED_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H