sled/include/sled/operations_chain.h
tqcq 3bcd014992
All checks were successful
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 46s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 8m7s
feat support chain operator
2024-03-15 11:40:49 +08:00

102 lines
2.8 KiB
C++

/**
* @file : operations_chain
* @created : Saturday Feb 03, 2024 12:40:36 CST
* @license : MIT
**/
#pragma once
#include "sled/make_ref_counted.h"
#ifndef SLED_OPERATIONS_CHAIN_H
#define SLED_OPERATIONS_CHAIN_H
#include "sled/optional.h"
#include "sled/ref_counted_base.h"
#include "sled/scoped_refptr.h"
#include <functional>
#include <memory>
#include <queue>
namespace sled {
namespace internal {
class Operation {
public:
virtual ~Operation() {}
virtual void Run() = 0;
};
template<typename FunctorT>
class OperationWithFunctor final : public Operation {
public:
OperationWithFunctor(FunctorT &&functor, std::function<void()> callback)
: functor_(std::forward<FunctorT>(functor)),
callback_(std::move(callback))
{}
~OperationWithFunctor() override {}
void Run() override
{
has_run_ = true;
auto functor = std::move(functor_);
functor(std::move(callback_));
}
private:
typename std::remove_reference<FunctorT>::type functor_;
std::function<void()> callback_;
bool has_run_ = false;
};
}// namespace internal
class OperationsChain final : public RefCountedNonVirtual<OperationsChain> {
public:
static scoped_refptr<OperationsChain> Create();
~OperationsChain();
OperationsChain(const OperationsChain &) = delete;
OperationsChain operator=(const OperationsChain &) = delete;
void SetOnChainEmptyCallback(std::function<void()> on_chain_empty_callback);
bool IsEmpty() const;
template<typename FunctorT>
scoped_refptr<OperationsChain> ChainOperation(FunctorT &&functor)
{
auto wrapper = new internal::OperationWithFunctor<FunctorT>(std::forward<FunctorT>(functor),
CreateOpeartionsChainCallback());
chained_operations_.push(std::unique_ptr<internal::OperationWithFunctor<FunctorT>>(wrapper));
if (chained_operations_.size() == 1) { chained_operations_.front()->Run(); }
return scoped_refptr<OperationsChain>(this);
}
private:
friend class CallbackHandle;
class CallbackHandle final : public RefCountedNonVirtual<CallbackHandle> {
public:
explicit CallbackHandle(scoped_refptr<OperationsChain> operations_chain);
~CallbackHandle();
CallbackHandle(const CallbackHandle &) = delete;
CallbackHandle &operator=(const CallbackHandle &) = delete;
void OnOperationComplete();
private:
scoped_refptr<OperationsChain> operations_chain_;
bool has_run_;
};
OperationsChain();
std::function<void()> CreateOpeartionsChainCallback();
void OnOperationComplete();
std::queue<std::unique_ptr<internal::Operation>> chained_operations_;
sled::optional<std::function<void()>> on_chain_empty_callback_;
};
}// namespace sled
#endif// SLED_OPERATIONS_CHAIN_H