#pragma once /** * @file transaction.h * @brief 极致性能 — 事务系统 + Command模式 + 无限撤销/重做 + 崩溃恢复 * * 核心组件: * - Transaction : begin/commit/rollback 事务 * - Command : 可撤销操作的抽象基类 * - UndoManager : 无限撤销/重做栈 + 事务日志 * - BrepCommand : BrepModel 操作的具体 Command 实现 * * @ingroup core */ #include #include #include #include #include #include #include #include #include #include #include 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; 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 make_command( std::function exec, std::function undo_fn, std::string desc = "") { return std::make_unique( 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 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> commands_; int64_t txn_id_ = 0; static std::atomic 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 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> undo_stack_; std::deque> redo_stack_; size_t max_undo_depth_ = 0; // 0 = unlimited // 事务日志 bool log_enabled_ = false; std::ofstream log_file_; std::string log_path_; std::atomic cmd_counter_{0}; /// 将命令序列化到日志文件 void log_command(const Command& cmd, TransactionLogEntry::Type type); /// 从日志中重放一条命令 std::unique_ptr replay_from_log(const TransactionLogEntry& entry); /// 清理多余撤销历史 void trim_undo_stack(); }; } // namespace vde::core