How and why one would use Boost signals2?(如何以及为什么要使用 Boost 信号 2?)
问题描述
学习c++并尝试熟悉一些模式.signals2 doc 显然有大量我可以用插槽和信号做的一系列事情.我不明白的是我应该将它用于哪些类型的应用程序(用例).
Learning c++ and trying to get familiar with some patterns. The signals2 doc clearly has a vast array of things I can do with slots and signals. What I don't understand is what types of applications (use cases) I should use it for.
我在思考状态机调度更改事件的思路.来自动态类型的背景(C#、Java 等),您将使用事件调度程序或静态引用或回调.
I'm thinking along the lines of a state machine dispatching change events. Coming from a dynamically typed background (C#,Java etc) you'd use an event dispatcher or a static ref or a callback.
在 C++ 中使用跨类回调有困难吗?这基本上是为什么signals2 存在的原因吗?
Are there difficulties in c++ with using cross-class callbacks? Is that essentially why signals2 exists?
示例案例之一是文档/视图.这种模式如何比使用函数向量并在循环中调用每个函数更适合,或者说 lambda 在注册的侦听类实例中调用状态更改?
One to the example cases is a document/view. How is this pattern better suited than say, using a vector of functions and calling each one in a loop, or say a lambda that calls state changes in registered listening class instances?
class Document
{
public:
typedef boost::signals2::signal<void ()> signal_t;
public:
Document()
{}
/* Connect a slot to the signal which will be emitted whenever
text is appended to the document. */
boost::signals2::connection connect(const signal_t::slot_type &subscriber)
{
return m_sig.connect(subscriber);
}
void append(const char* s)
{
m_text += s;
m_sig();
}
const std::string& getText() const
{
return m_text;
}
private:
signal_t m_sig;
std::string m_text;
};
和
class TextView
{
public:
TextView(Document& doc): m_document(doc)
{
m_connection = m_document.connect(boost::bind(&TextView::refresh, this));
}
~TextView()
{
m_connection.disconnect();
}
void refresh() const
{
std::cout << "TextView: " << m_document.getText() << std::endl;
}
private:
Document& m_document;
boost::signals2::connection m_connection;
};
推荐答案
Boost.Signals2
不仅仅是回调数组",它还有很多附加值.IMO,最重要的几点是:
Boost.Signals2
is not just "an array of callbacks", it has a lot of added value. IMO, the most important points are:
- 线程安全:多个线程可以同时连接/断开/调用同一个信号,而不会引入竞争条件.这在与异步子系统(例如在其自己的线程中运行的活动对象)通信时特别有用.
connection
和scoped_connection
句柄允许在没有直接访问信号
的情况下断开连接.请注意,这是断开无与伦比的插槽的唯一方法,例如boost::function
(或std::function
).- 临时插槽阻塞.提供一种干净的方法来暂时禁用侦听模块(例如,当用户请求暂停接收视图中的消息时).
自动插槽寿命跟踪:信号自动与过期"插槽断开连接.考虑当插槽是引用由
shared_ptr
s 管理的不可复制对象的绑定器时的情况:
- Thread-safety: several threads may connect/disconnect/invoke the same signal concurrently, without introducing race conditions. This is especially useful when communicating with an asynchronous subsystem, like an Active Object running in its own thread.
connection
andscoped_connection
handles that allow disconnection without having direct access to thesignal
. Note that this is the only way to disconnect incomparable slots, likeboost::function
(orstd::function
).- Temporary slot blocking. Provides a clean way to temporarily disable a listening module (eg. when a user requests to pause receiving messages in a view).
Automatic slot lifespan tracking: a signal disconnects automatically from "expired" slots. Consider the situation when a slot is a binder referencing a non-copyable object managed by
shared_ptr
s:
shared_ptr<listener> l = listener::create();
auto slot = bind(&listener::listen, l.get()); // we don't want aSignal_ to affect `listener` lifespan
aSignal_.connect(your_signal_type::slot_type(slot).track(l)); // but do want to disconnect automatically when it gets destroyed
当然,人们可以自己使用函数向量并在循环中调用每个函数"等重新实现上述所有功能,但问题是它如何比 Boost.Signals2代码>.重新发明轮子很少是个好主意.
Certainly, one can re-implement all the above functionality on his own "using a vector of functions and calling each one in a loop" etc, but the question is how it would be better than Boost.Signals2
. Re-inventing the wheel is rarely a good idea.
这篇关于如何以及为什么要使用 Boost 信号 2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何以及为什么要使用 Boost 信号 2?
基础教程推荐
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 从 std::cin 读取密码 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01