Files
ViewDesignEngine/include/vde/core/transaction.h
T

284 lines
9.2 KiB
C++
Raw Normal View History

#pragma once
/**
* @file transaction.h
* @brief 极致性能 — 事务系统 + Command模式 + 无限撤销/重做 + 崩溃恢复
*
* 核心组件:
* - Transaction : begin/commit/rollback 事务
* - Command : 可撤销操作的抽象基类
* - UndoManager : 无限撤销/重做栈 + 事务日志
* - BrepCommand : BrepModel 操作的具体 Command 实现
*
* @ingroup core
*/
#include <vector>
#include <string>
#include <memory>
#include <functional>
#include <deque>
#include <fstream>
#include <sstream>
#include <ctime>
#include <chrono>
#include <cstdint>
#include <atomic>
namespace vde::core {
// ═══════════════════════════════════════════════════════════════════════════
// Command 模式
// ═══════════════════════════════════════════════════════════════════════════
/// 可撤销操作的抽象基类
///
/// 每个 Command 封装一个原子操作,支持执行和撤销。
/// 子类需实现 execute() 和 undo()。
class Command {
public:
virtual ~Command() = default;
/// 执行操作
virtual void execute() = 0;
/// 撤销操作(将状态恢复到执行前)
virtual void undo() = 0;
/// 获取操作描述
[[nodiscard]] virtual std::string description() const { return "Command"; }
/// 合并两个命令(可选优化)
/// @return true 若合并成功(this 吸收了 other)
virtual bool merge(Command* /*other*/) { return false; }
/// 命令 ID(用于日志)
[[nodiscard]] int64_t id() const { return id_; }
void set_id(int64_t id) { id_ = id; }
private:
int64_t id_ = 0;
};
/// 可调用对象包装的 Command
///
/// @code
/// auto cmd = make_command(
/// []{ do_something(); },
/// []{ undo_it(); },
/// "My operation");
/// @endcode
class LambdaCommand : public Command {
public:
using Func = std::function<void()>;
LambdaCommand(Func exec, Func undo_fn, std::string desc = "")
: exec_(std::move(exec))
, undo_(std::move(undo_fn))
, desc_(std::move(desc)) {}
void execute() override { if (exec_) exec_(); }
void undo() override { if (undo_) undo_(); }
[[nodiscard]] std::string description() const override { return desc_; }
private:
Func exec_;
Func undo_;
std::string desc_;
};
/// 便捷工厂函数
inline std::unique_ptr<Command> make_command(
std::function<void()> exec,
std::function<void()> undo_fn,
std::string desc = "")
{
return std::make_unique<LambdaCommand>(
std::move(exec), std::move(undo_fn), std::move(desc));
}
// ═══════════════════════════════════════════════════════════════════════════
// 事务日志条目
// ═══════════════════════════════════════════════════════════════════════════
/// 事务日志条目
///
/// 持久化到事务日志文件,用于崩溃恢复。
struct TransactionLogEntry {
enum class Type : uint8_t {
BEGIN = 0, ///< 事务开始
COMMAND = 1, ///< 命令执行
COMMIT = 2, ///< 事务提交
ROLLBACK = 3, ///< 事务回滚
CHECKPOINT = 4, ///< 检查点
};
Type type;
int64_t transaction_id;
int64_t command_id;
int64_t timestamp; ///< unix 微秒时间戳
std::string description; ///< 命令描述(COMMAND 类型时有效)
/// 序列化为一行
[[nodiscard]] std::string serialize() const;
/// 从一行反序列化
static TransactionLogEntry deserialize(const std::string& line);
};
// ═══════════════════════════════════════════════════════════════════════════
// Transaction
// ═══════════════════════════════════════════════════════════════════════════
/// 事务
///
/// 封装一组 Command 的原子执行。支持 begin/commit/rollback。
/// 事务在 commit 时将命令推送到 UndoManager。
///
/// @code
/// Transaction txn;
/// txn.begin();
/// txn.execute(make_command(...));
/// txn.execute(make_command(...));
/// txn.commit(); // 或 txn.rollback()
/// @endcode
class Transaction {
public:
Transaction();
~Transaction();
Transaction(const Transaction&) = delete;
Transaction& operator=(const Transaction&) = delete;
/// 开始事务
void begin();
/// 执行一条命令(加入事物缓冲区)
/// @param cmd 要执行的命令
void execute(std::unique_ptr<Command> cmd);
/// 提交事务(执行所有命令 → 加入 UndoManager
void commit();
/// 回滚事务(撤销已执行命令 → 丢弃)
void rollback();
/// 是否处于活跃事务中
[[nodiscard]] bool is_active() const { return active_; }
/// 当前缓冲命令数
[[nodiscard]] size_t command_count() const { return commands_.size(); }
private:
bool active_ = false;
std::vector<std::unique_ptr<Command>> commands_;
int64_t txn_id_ = 0;
static std::atomic<int64_t> next_txn_id_;
};
// ═══════════════════════════════════════════════════════════════════════════
// UndoManager — 无限撤销/重做
// ═══════════════════════════════════════════════════════════════════════════
/// 撤销管理器
///
/// 维护无限撤销栈和重做栈。
/// 支持命令合并(连续同类型操作合并为一个)、事务日志与崩溃恢复。
///
/// @code
/// UndoManager um;
/// um.execute(make_command(...));
/// um.undo(); // 撤销最后一步
/// um.redo(); // 重做
/// um.save_checkpoint("save/checkpoint.dat"); // 持久化
/// @endcode
class UndoManager {
public:
UndoManager();
~UndoManager();
UndoManager(const UndoManager&) = delete;
UndoManager& operator=(const UndoManager&) = delete;
/// 执行命令并推入撤销栈
/// @param cmd 要执行的命令
/// @param merge 是否尝试与栈顶命令合并
void execute(std::unique_ptr<Command> cmd, bool merge = false);
/// 撤销最近一步操作
/// @return true 若撤销成功
bool undo();
/// 重做最近撤销的操作
/// @return true 若重做成功
bool redo();
/// 是否可撤销
[[nodiscard]] bool can_undo() const { return !undo_stack_.empty(); }
/// 是否可重做
[[nodiscard]] bool can_redo() const { return !redo_stack_.empty(); }
/// 撤销栈深度
[[nodiscard]] size_t undo_depth() const { return undo_stack_.size(); }
/// 重做栈深度
[[nodiscard]] size_t redo_depth() const { return redo_stack_.size(); }
/// 清空所有历史
void clear();
/// 获取撤销栈顶命令描述
[[nodiscard]] std::string undo_description() const;
/// 获取重做栈顶命令描述
[[nodiscard]] std::string redo_description() const;
// ── 事务日志 ──
/// 开启事务日志(追加模式)
/// @param filepath 日志文件路径
/// @return true 若成功
bool enable_log(const std::string& filepath);
/// 关闭事务日志
void disable_log();
/// 是否开启了事务日志
[[nodiscard]] bool log_enabled() const { return log_enabled_; }
/// 写入检查点
void write_checkpoint();
/// 从日志文件恢复(崩溃恢复)
/// @param filepath 日志文件路径
/// @return 恢复的命令数(0 表示无日志或恢复失败)
size_t recover_from_log(const std::string& filepath);
/// 设置最大撤销深度(0 = 无限)
void set_max_undo_depth(size_t max_depth) { max_undo_depth_ = max_depth; }
/// 获取已执行命令总数
[[nodiscard]] int64_t total_commands() const { return cmd_counter_.load(); }
private:
std::deque<std::unique_ptr<Command>> undo_stack_;
std::deque<std::unique_ptr<Command>> redo_stack_;
size_t max_undo_depth_ = 0; // 0 = unlimited
// 事务日志
bool log_enabled_ = false;
std::ofstream log_file_;
std::string log_path_;
std::atomic<int64_t> cmd_counter_{0};
/// 将命令序列化到日志文件
void log_command(const Command& cmd, TransactionLogEntry::Type type);
/// 从日志中重放一条命令
std::unique_ptr<Command> replay_from_log(const TransactionLogEntry& entry);
/// 清理多余撤销历史
void trim_undo_stack();
};
} // namespace vde::core