C++并发编程实战:消息传递框架与ATM系统实现详解
消息传递框架概述
在现代C++并发编程中,消息传递是一种重要的线程间通信机制。消息传递框架通过队列在不同线程间传递消息,避免了共享数据带来的复杂性,使并发程序设计更加清晰和安全。
核心组件实现
消息队列基础结构
消息队列是框架的核心,它需要处理多种类型的消息。我们采用面向对象的设计思路:
- 基类设计:
message_base
作为所有消息的基类,提供统一的接口 - 模板包装器:
wrapped_message
模板类负责包装具体消息类型 - 线程安全队列:使用互斥锁和条件变量保证线程安全
struct message_base {
virtual ~message_base() {}
};
template<typename Msg>
struct wrapped_message : message_base {
Msg contents;
explicit wrapped_message(Msg const& contents_) : contents(contents_) {}
};
发送端实现
发送端(sender
)设计要点:
- 轻量级包装器,仅持有队列指针
- 支持多种消息类型的发送
- 默认构造的sender不关联任何队列
class sender {
queue* q;
public:
sender() : q(nullptr) {}
explicit sender(queue* q_) : q(q_) {}
template<typename Message>
void send(Message const& msg) {
if(q) q->push(msg);
}
};
接收端实现
接收端(receiver
)设计更为复杂:
- 拥有自己的消息队列
- 提供隐式转换为sender的能力
- 通过
wait()
方法返回调度器
class receiver {
queue q;
public:
operator sender() { return sender(&q); }
dispatcher wait() { return dispatcher(&q); }
};
消息调度机制
调度器核心设计
调度器(dispatcher
)负责消息的分发处理:
- 消息循环:持续等待并处理消息
- 类型检查:动态类型转换确定消息类型
- 链式处理:支持多个处理器的串联
class dispatcher {
queue* q;
bool chained;
void wait_and_dispatch() {
for(;;) {
auto msg = q->wait_and_pop();
dispatch(msg);
}
}
bool dispatch(std::shared_ptr<message_base> const& msg) {
if(dynamic_cast<wrapped_message<close_queue>*>(msg.get())) {
throw close_queue();
}
return false;
}
public:
template<typename Message, typename Func>
TemplateDispatcher<dispatcher, Message, Func> handle(Func&& f) {
return TemplateDispatcher<dispatcher, Message, Func>(
q, this, std::forward<Func>(f));
}
};
模板化调度器
TemplateDispatcher
是调度器的模板化扩展:
- 支持特定消息类型的处理
- 维护处理链关系
- 提供灵活的消息处理方式
template<typename PreviousDispatcher, typename Msg, typename Func>
class TemplateDispatcher {
// 实现细节...
public:
template<typename OtherMsg, typename OtherFunc>
TemplateDispatcher<TemplateDispatcher, OtherMsg, OtherFunc> handle(OtherFunc&& of) {
return TemplateDispatcher<TemplateDispatcher, OtherMsg, OtherFunc>(
q, this, std::forward<OtherFunc>(of));
}
};
ATM系统实现
系统架构设计
ATM系统由三个主要组件构成:
- ATM机:处理用户交互和业务流程
- 银行系统:验证账户和完成交易
- 用户界面:显示信息和接收输入
消息类型定义
系统定义了丰富的消息类型来支持各种操作:
struct withdraw {
std::string account;
unsigned amount;
mutable messaging::sender atm_queue;
// 构造函数...
};
struct withdraw_ok {};
struct withdraw_denied {};
// 更多消息类型...
状态机实现
ATM核心是一个状态机,处理各种状态转换:
class atm {
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
// 状态处理函数
void process_withdrawal() {
incoming.wait()
.handle<withdraw_ok>(/*...*/)
.handle<withdraw_denied>(/*...*/)
.handle<cancel_pressed>(/*...*/);
}
// 其他状态函数...
public:
void run() {
state = &atm::waiting_for_card;
try {
for(;;) { (this->*state)(); }
} catch(messaging::close_queue const&) {}
}
};
系统集成与运行
组件初始化
int main() {
bank_machine bank;
interface_machine interface_hardware;
atm machine(bank.get_sender(), interface_hardware.get_sender());
// 启动各组件线程
std::thread bank_thread(&bank_machine::run, &bank);
std::thread if_thread(&interface_machine::run, &interface_hardware);
std::thread atm_thread(&atm::run, &machine);
// 等待线程结束
atm_thread.join();
bank_thread.join();
if_thread.join();
}
设计模式分析
这个实现体现了多种设计模式的综合应用:
- 状态模式:ATM的状态转换
- 观察者模式:消息的发布-订阅机制
- 模板方法模式:消息处理的通用框架
- 责任链模式:消息的链式处理
性能与安全考虑
- 线程安全:所有共享数据访问都通过互斥锁保护
- 异常安全:正确处理异常情况下的资源释放
- 性能优化:减少锁竞争,使用条件变量等待
- 资源管理:使用智能指针自动管理内存
总结
这个C++并发消息传递框架展示了现代C++在并发编程中的强大能力。通过消息队列和状态机的组合,我们可以构建出清晰、可维护的并发系统。ATM示例完整地演示了如何将这一框架应用于实际业务场景,为开发者提供了有价值的参考实现。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考