- 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.
526 lines
17 KiB
C++
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;
|
|
}
|
|
} |