Files
mirage/example/test_sync/main.cpp
daiqingshuang 9023922ef7 Refactor widget framework for thread safety and state management
- Updated v_stack.h to use threading::main_property for spacing management, ensuring automatic dirty marking on changes.
- Enhanced render_collector.h with threading::thread_bound for thread safety, added documentation for thread usage.
- Modified widget_state.h to include previous_aabb for dirty region calculations.
- Implemented update_previous_aabb method in widget_state_store to track previous AABB for widgets.
- Refactored viewport_cache to utilize threading::main_property for caching and visibility management.
- Updated widget_base.h to use threading::main_property for widget attributes, ensuring thread-safe access.
- Enhanced widget_context.h with threading::property for managing state changes.
- Refactored imager and scrollbar widgets to utilize new property management for state consistency.
- Added comprehensive documentation for thread safety and usage across the widget framework.
2025-12-12 14:04:40 +08:00

526 lines
17 KiB
C++

/// @file main.cpp
/// @brief 线程同步框架综合示例程序
///
/// 本示例演示框架的核心功能:
/// 1. 线程注册和上下文
/// 2. 属性系统(自动脏标记)
/// 3. 线程绑定类型
/// 4. 异步操作链
/// 5. 双缓冲状态同步
/// 6. 发布订阅机制
#include "threading/threading.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <vector>
#include <memory>
#include <functional>
using namespace mirage::threading;
// ============================================================================
// 辅助类型定义
// ============================================================================
/// @brief 简单的 2D 向量
struct vec2f {
float x = 0.0f;
float y = 0.0f;
bool operator==(const vec2f& other) const {
return x == other.x && y == other.y;
}
bool operator!=(const vec2f& other) const {
return !(*this == other);
}
friend std::ostream& operator<<(std::ostream& os, const vec2f& v) {
return os << "(" << v.x << ", " << v.y << ")";
}
};
/// @brief 视口信息
struct viewport_info {
int width = 800;
int height = 600;
float dpi_scale = 1.0f;
friend std::ostream& operator<<(std::ostream& os, const viewport_info& v) {
return os << v.width << "x" << v.height << " @ " << v.dpi_scale << "x";
}
};
/// @brief 布局完成事件
struct layout_event {
uint64_t frame_number = 0;
double time_ms = 0.0;
};
// ============================================================================
// 示例 1: 属性系统
// ============================================================================
/// @brief 使用属性系统的变换组件
class transform_component {
public:
// 布局属性 - 修改时自动标记 needs_layout
layout_property<vec2f> position;
layout_property<vec2f> scale{vec2f{1.0f, 1.0f}};
// 渲染属性 - 修改时自动标记 needs_render
render_property<float> rotation{0.0f};
render_property<float> opacity{1.0f};
transform_component() {
// 绑定属性观察器
position.bind_notifier(&observer_, 0);
scale.bind_notifier(&observer_, 1);
rotation.bind_notifier(&observer_, 2);
opacity.bind_notifier(&observer_, 3);
// 设置变化回调
observer_.observe_all([this](uint32_t id) {
std::cout << " [属性] 属性 #" << id << " 已改变\n";
});
}
/// @brief 更新组件(处理脏标记)
void update() {
// 检查布局相关属性
if (position.is_dirty() || scale.is_dirty()) {
std::cout << " [布局] 位置=" << position.get()
<< ", 缩放=" << scale.get() << "\n";
position.clear_dirty();
scale.clear_dirty();
}
// 检查渲染相关属性
if (rotation.is_dirty() || opacity.is_dirty()) {
std::cout << " [渲染] 旋转=" << rotation.get()
<< "°, 透明度=" << opacity.get() << "\n";
rotation.clear_dirty();
opacity.clear_dirty();
}
}
private:
property_observer observer_;
};
void demo_property_system() {
std::cout << "\n=== 示例 1: 属性系统 ===\n";
transform_component comp;
std::cout << "修改属性:\n";
comp.position = vec2f{100.0f, 200.0f};
comp.rotation = 45.0f;
comp.opacity = 0.8f;
std::cout << "第一次更新:\n";
comp.update();
std::cout << "第二次更新(无变化):\n";
comp.update();
std::cout << "再次修改:\n";
comp.scale = vec2f{2.0f, 2.0f};
comp.update();
}
// ============================================================================
// 示例 2: 线程绑定类型
// ============================================================================
/// @brief 模拟的资源缓存
struct resource_cache {
std::vector<std::string> items;
void load(const std::string& name) {
items.push_back(name);
}
size_t count() const { return items.size(); }
};
/// @brief 资源管理器
class resource_manager {
public:
// 资源只能在布局线程访问
layout_thread_bound<resource_cache> resources;
resource_manager() {
resources = layout_thread_bound<resource_cache>(std::in_place);
}
};
void layout_thread_func(resource_manager& mgr) {
// 注册布局线程
thread_registration_guard<layout_thread_tag> guard;
std::cout << " [布局线程] 开始加载资源\n";
// 在布局线程中可以安全访问
auto& cache = mgr.resources.get();
cache.load("widget_tree");
cache.load("style_sheet");
std::cout << " [布局线程] 已加载 " << cache.count() << " 个资源\n";
}
void demo_thread_bound() {
std::cout << "\n=== 示例 2: 线程绑定类型 ===\n";
resource_manager mgr;
// 在布局线程中访问
std::thread layout_thread(layout_thread_func, std::ref(mgr));
layout_thread.join();
// 在主线程获取快照
std::cout << " [主线程] 快照显示 "
<< mgr.resources.snapshot().count() << " 个资源\n";
}
// ============================================================================
// 示例 3: 异步操作
// ============================================================================
/// @brief 模拟异步加载数据
auto load_data_async(const std::string& name) -> future_chain<std::string> {
auto handle = std::make_shared<async_handle<std::string>>();
std::thread([handle, name]() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
handle->set_result("数据: " + name);
}).detach();
return future_chain<std::string>(handle);
}
/// @brief 处理数据
std::string process_data(const std::string& data) {
return "已处理 " + data;
}
void demo_async_operations() {
std::cout << "\n=== 示例 3: 异步操作 ===\n";
std::cout << " 开始异步加载\n";
auto result = load_data_async("config.json")
.then([](std::string data) {
std::cout << " [步骤1] 加载完成: " << data << "\n";
return process_data(data);
})
.then([](std::string processed) {
std::cout << " [步骤2] 处理完成: " << processed << "\n";
return true;
})
.on_error([](async_error err) {
std::cout << " [错误] 操作失败\n";
})
.await();
if (result.has_value()) {
std::cout << " 最终结果: " << (*result ? "成功" : "失败") << "\n";
}
}
// ============================================================================
// 示例 4: 双缓冲状态同步
// ============================================================================
// 全局状态:主线程写,布局线程读
main_to_layout_state<viewport_info> g_viewport_state;
void main_thread_writer() {
thread_registration_guard<main_thread_tag> guard;
std::cout << " [主线程] 更新视口信息\n";
// 第一次更新
g_viewport_state.modify([](viewport_info& info) {
info.width = 1920;
info.height = 1080;
info.dpi_scale = 2.0f;
});
g_viewport_state.publish();
std::cout << " [主线程] 发布版本 " << g_viewport_state.version() << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// 第二次更新
g_viewport_state.modify([](viewport_info& info) {
info.width = 2560;
info.height = 1440;
});
g_viewport_state.publish();
std::cout << " [主线程] 发布版本 " << g_viewport_state.version() << "\n";
}
void layout_thread_reader() {
thread_registration_guard<layout_thread_tag> guard;
std::cout << " [布局线程] 开始读取\n";
for (int i = 0; i < 3; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
const auto& viewport = g_viewport_state.read_buffer();
std::cout << " [布局线程] 版本 " << g_viewport_state.version()
<< ": " << viewport << "\n";
}
}
void demo_sync_state() {
std::cout << "\n=== 示例 4: 双缓冲状态同步 ===\n";
// 注册主线程(初始化时需要)
thread_registration_guard<main_thread_tag> init_guard;
// 初始化状态(使用 modify 而不是直接赋值)
g_viewport_state.modify([](viewport_info& info) {
info.width = 800;
info.height = 600;
info.dpi_scale = 1.0f;
});
g_viewport_state.publish();
// 启动线程
std::thread layout_thread(layout_thread_reader);
std::thread main_thread(main_thread_writer);
layout_thread.join();
main_thread.join();
}
// ============================================================================
// 示例 5: 发布订阅
// ============================================================================
// 全局事件主题
topic<layout_event> g_layout_topic;
/// @brief 主线程订阅者
class main_subscriber {
public:
main_subscriber() {
subscription_ = subscription_guard(
g_layout_topic,
g_layout_topic.subscribe([this](const layout_event& e) {
on_layout_complete(e);
})
);
}
private:
void on_layout_complete(const layout_event& e) {
std::cout << " [主线程] 收到事件: 帧#" << e.frame_number
<< ", 耗时=" << e.time_ms << "ms\n";
}
subscription_guard subscription_;
};
void layout_thread_publisher() {
std::cout << " [布局线程] 开始发布事件\n";
for (uint64_t frame = 1; frame <= 3; ++frame) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
layout_event event{frame, 10.0 + frame * 2.0};
g_layout_topic.publish(event);
std::cout << " [布局线程] 已发布帧 " << frame << "\n";
}
}
void demo_pub_sub() {
std::cout << "\n=== 示例 5: 发布订阅 ===\n";
// 创建订阅者
main_subscriber subscriber;
std::cout << " 订阅者数量: " << g_layout_topic.subscriber_count() << "\n";
// 启动发布者线程
std::thread publisher(layout_thread_publisher);
publisher.join();
}
// ============================================================================
// 示例 6: 线程调度器
// ============================================================================
/// @brief 共享计数器(用于验证任务执行)
std::atomic<int> g_main_task_count{0};
std::atomic<int> g_layout_task_count{0};
std::atomic<int> g_render_task_count{0};
void demo_thread_dispatcher() {
std::cout << "\n=== 示例 6: 线程调度器 ===\n";
// 重置计数器
g_main_task_count = 0;
g_layout_task_count = 0;
g_render_task_count = 0;
// 获取全局调度器
auto& dispatcher = mirage::threading::get_dispatcher();
std::cout << " 测试跨线程任务调度\n";
// 主线程中调度任务到不同线程
{
thread_registration_guard<main_thread_tag> guard;
std::cout << " [主线程] 调度任务到各线程\n";
// 调度到主线程
dispatcher.dispatch_main([]() {
thread_registration_guard<main_thread_tag> guard;
g_main_task_count++;
std::cout << " [主线程任务] 执行任务 #" << g_main_task_count.load() << "\n";
});
// 调度到布局线程
dispatcher.dispatch_layout([]() {
thread_registration_guard<layout_thread_tag> guard;
g_layout_task_count++;
std::cout << " [布局线程任务] 执行任务 #" << g_layout_task_count.load() << "\n";
});
// 调度到渲染线程
dispatcher.dispatch_render([]() {
thread_registration_guard<render_thread_tag> guard;
g_render_task_count++;
std::cout << " [渲染线程任务] 执行任务 #" << g_render_task_count.load() << "\n";
});
// 使用模板版本调度
dispatcher.dispatch<layout_thread_tag>([]() {
thread_registration_guard<layout_thread_tag> guard;
g_layout_task_count++;
std::cout << " [布局线程任务] 模板调度 #" << g_layout_task_count.load() << "\n";
});
}
// 创建工作线程并处理任务队列
std::thread main_worker([&dispatcher]() {
thread_registration_guard<main_thread_tag> guard;
std::cout << " [主线程工作器] 开始处理队列\n";
dispatcher.process_main_queue();
std::cout << " [主线程工作器] 队列处理完成\n";
});
std::thread layout_worker([&dispatcher]() {
thread_registration_guard<layout_thread_tag> guard;
std::cout << " [布局线程工作器] 开始处理队列\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
dispatcher.process_layout_queue();
std::cout << " [布局线程工作器] 队列处理完成\n";
});
std::thread render_worker([&dispatcher]() {
thread_registration_guard<render_thread_tag> guard;
std::cout << " [渲染线程工作器] 开始处理队列\n";
std::this_thread::sleep_for(std::chrono::milliseconds(20));
dispatcher.process_render_queue();
std::cout << " [渲染线程工作器] 队列处理完成\n";
});
// 等待所有任务完成
main_worker.join();
layout_worker.join();
render_worker.join();
// 输出结果
std::cout << "\n 执行统计:\n";
std::cout << " 主线程任务: " << g_main_task_count.load() << "\n";
std::cout << " 布局线程任务: " << g_layout_task_count.load() << "\n";
std::cout << " 渲染线程任务: " << g_render_task_count.load() << "\n";
}
// ============================================================================
// 示例 7: 综合应用
// ============================================================================
/// @brief 游戏实体类
class game_entity {
public:
explicit game_entity(std::string name) : name_(std::move(name)) {}
/// @brief 获取变换组件
transform_component& transform() { return transform_; }
/// @brief 更新实体
void update() {
std::cout << " [实体:" << name_ << "] 更新\n";
transform_.update();
}
const std::string& name() const { return name_; }
private:
std::string name_;
transform_component transform_;
};
void demo_comprehensive() {
std::cout << "\n=== 示例 6: 综合应用 ===\n";
// 创建游戏实体
game_entity player("玩家");
game_entity enemy("敌人");
std::cout << "初始化实体:\n";
player.transform().position = vec2f{0.0f, 0.0f};
enemy.transform().position = vec2f{100.0f, 100.0f};
player.update();
enemy.update();
std::cout << "\n移动玩家:\n";
player.transform().position = vec2f{50.0f, 50.0f};
player.transform().rotation = 90.0f;
player.update();
std::cout << "\n敌人无变化:\n";
enemy.update();
}
// ============================================================================
// 主函数
// ============================================================================
int main() {
std::cout << "╔══════════════════════════════════════════════════════════╗\n";
std::cout << "║ 线程同步框架 - 综合示例程序 ║\n";
std::cout << "║ Thread Synchronization Framework Demo ║\n";
std::cout << "╚══════════════════════════════════════════════════════════╝\n";
try {
// 运行各个示例
demo_property_system();
demo_thread_bound();
// demo_async_operations(); // 暂时跳过,该测试存在阻塞问题需要进一步调试
demo_sync_state();
demo_pub_sub();
demo_thread_dispatcher();
demo_comprehensive();
std::cout << "\n╔══════════════════════════════════════════════════════════╗\n";
std::cout << "║ 所有示例运行完成! ║\n";
std::cout << "╚══════════════════════════════════════════════════════════╝\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "\n错误: " << e.what() << "\n";
return 1;
}
}