如何使用boost电路小信号模型信号

系统辅助类排行
喜欢这个应用的还喜欢1136人阅读
编程语言 / C++(21)
Slots aren't expected to exist indefinately
after they are connected. Often slots are only used to receive a few events and
are then disconnected, and the programmer needs control to decide when a slot
should no longer be connected.
Signal/slot disconnections occur
when any of these conditions occur:
-The connection is
explicitly disconnected via the connection's &&
disconnect
method directly, or indirectly via the signal's
disconnect method or scoped_connection's
destructor.&&
-A trackable object bound &
to the slot is destroyed.
-The signal is destroyed.
Disconnecting slots.
boost::signals::connection
c = sig.connect(HelloWorld());
(c.connected()) {
// c is still connected to the signal
// Prints &Hello, World!&
c.disconnect();
// Disconnect the HelloWorld object
assert(!c.connected());
//c isn't connected any more
// Does nothing: there are no connected slots
boost::signals::connection
c = sig.connect(HelloWorld());
// Prints &Hello, World!&
c.block();
// block the slot
assert(c.blocked());
// No output: the slot is blocked
c.unblock();
// unblock the slot
// Prints &Hello, World!&
Slots in the Boost.Signals library are
created from arbitrary function objects, and therefore have no fixed type.
However, it is commonplace to require that slots be passed through interfaces
that cannot be templates. Slots can be passed via the
for each particular signal
type and any function object compatible with the signature of the signal can be
passed to a
parameter.
class Button
typedef boost::signal&void (int x, int y)& OnC
void doOnClick(const OnClick::slot_type& slot);
OnClick onC
void Button::doOnClick(
const OnClick::slot_type& slot
onClick.connect
void printCoordinates(long x, long y)
std::cout && &(& && x && &, & && y && &)/n&;
void f(Button& button)
button.doOnClick(&printCoordinates);
The doOnClick
method is now functionally equivalent to the connect
method of the onClick
signal, but the details of the doOnClick
&can be hidden in an implementation detail file.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:85698次
积分:1066
积分:1066
排名:千里之外
原创:17篇
评论:10条
(1)(1)(1)(1)(2)(5)(15)Is it possible, and if so, how can I create a signal/slot in Qt that is a const reference to a shared_ptr?
I want a signal that looks like this:
void signal( shared_ptr&SomeClass& const & )
I know how to do this without a constant reference, that is simply the type shared_ptr&SomeClass& but for efficiency* reasons I'd like to avoid the copying. The same syntax for reference type isn't working:
Q_DECLARE_METATYPE(shared_ptr&SomeClass& const &)
qRegisterMetaType&shared_ptr&SomeClass& const&&();
Many of the standard APIs have QString const & so I assume it is fundamentally possible and I just can't figure out the syntax.
**The biggest problem for performance is not the copying time, but the amount of mutex locking/unlocking as the object is copied to every receiver -- there are lots of them. As multiple threads use the object this introduces a noticeable slow-down/bottleneck.
If the shared_ptr does in fact just use an atomic op this cost is also trivial, the general question about const reference in signals remains however.*
解决方案 So far I have found that I can simply do this:
Q_DECLARE_METATYPE(shared_ptr&SomeClass&)
qRegisterMetaType&shared_ptr&SomeClass& &();
qRegisterMetaType&shared_ptr&SomeClass& &("std::shared_ptr&SomeClass&const&");
I'm trying to verify now whether this truly works correctly. The documentation here isn't clear on what actually happens. It appears that the const reference type in a signal/slot will just be marshalled as a normal shared_ptr&SomeClass&, which is totally okay here. Having some sort of guarantee that this is supposed to work as such would be nice however.
I have the feeling that the simple shared_ptr&SomeClass& version is all that is needed and it is the boost namespace that is interfering with the signals. The second version appears just to register the signal in the global namespace for easier use.
I can confirm, from testing, that the const & part is, as alluded to, completely ignored in queued connections. Each connected slot gets a new copy of the object.
This is very unfortunate. :(
Further tests show that the & is used for the slot, but in an unusual fashion. The copy of the object is still created for the queued connection, but if you don't use a reference another copy will be created for the call.
Thus there although every connect will end up copying the data for a queued connection, the references still help a bit. And also if you do have a few signals sent locally (same thread) you may avoid even more copying.
本文地址: &
是否有可能,如果是这样,我怎么可以创建Qt的信号/插槽是一个常量引用一个shared_ptr?我想,看起来像这样的信号: 空信号(shared_ptr的< SomeClass的>常量和放大器;) 我知道如何做到这一点没有一个恒定的参考,那简直是键入的shared_ptr< SomeClass的> ,但出于效率*的原因,我想避免复制。为引用类型相同的语法不工作:
Q_DECLARE_METATYPE(shared_ptr的< SomeClass的>常量和放大器;)qRegisterMetaType<&的shared_ptr LT; SomeClass的>常量和放大器;>(); 很多标准的API有 QString的常量和放大器; ,所以我认为它基本上是可能的,我只是想不通语法 **性能最大的问题是不复制时间,但互斥锁定/解锁作为对象的量被复制到每接收器 - 有很多人。因为多个线程使用此引入明显减慢/瓶颈的对象。如果shared_ptr的其实不只是使用原子操作这笔费用也是微不足道的,关于信号常引用的一般问题不过仍然存在。* 解决方案 到目前为止,我发现,我可以简单地做到这一点:
Q_DECLARE_METATYPE(shared_ptr的< SomeClass的>)qRegisterMetaType<&的shared_ptr LT; SomeClass的> >();qRegisterMetaType<&的shared_ptr LT; SomeClass的> >(“的std :: shared_ptr的< SomeClass的>常量和放大器;”); 我想现在要核实是否这个真正正常工作。这里的文档不是对实际发生的情况不清楚。目前看来,在一个信号/插槽const的引用类型只会被整理为正常的shared_ptr< SomeClass的> ,这完全是没事在这里。有某种保证,这是应该这样的工作将是很好,但是。我有一种感觉,简单的的shared_ptr< SomeClass的> 版本是所有需要,它是升压命名空间与信号干扰。第二个版本只是出现在注册全局命名空间的信号,以方便使用。我可以证实,从测试,即常量和放大器; 部分,如提到的,在排队的连接完全忽略。每个连接插槽获取对象的新副本。这是非常不幸的。 (进一步的试验表明,&安培; 用于插槽,但在一个不寻常的方式。对象的副本还在为排队连接创建的,但如果你不使用引用另一个副本会为呼叫创建。 因此,有虽然每个连接最终将复制的数据排队连接时,引用仍然有点帮助。而且如果你有本地发出的一些信号(同一个线程),你可能避免更多的复制。
本文地址: &
扫一扫关注官方微信zz_yun 的BLOG
用户名:zz_yun
文章数:565
评论数:158
访问量:2138576
注册日期:
阅读量:5863
阅读量:12276
阅读量:370254
阅读量:1064688
51CTO推荐博文
Qt 的信号槽和 Boost.Signals 由于有着截然不同的设计目标,因此二者的实现、强度也十分不同。将二者混合在一起使用也不是不可能的,我们将在本系统的最后一部分来讨论这个问题。使用信号槽信号槽是伟大的工具,但是如何能更好的使用它们?相比于直接函数调用,有三点值得我们的注意。一个信号槽的调用:或许会比直接函数调用耗费更多的时间/空间;可能不能使用 inline;对于代码阅读者来说可能并不友好。使用信号槽进行解耦,我们获得的最大的好处是,连接两端的对象不需要知道对方的任何信息。Button 同动作的连接是一个很典型的案例。例如如下信息:class Elevator{public:enum Direction { DownDirection=-1, NoDirection=0, UpDirection=1 };enum State { IdleState, LoadingState, MovingState };// ...// signals:void floorChanged(int newFloor );void stateChanged( State newState );void directionChanged( Direction newDirection );};Elevator 类,也就是电梯,不需要知道有多少显示器正在监听它的信号,也不需要知道这些显示器的任何信息。每一层可能有一个屏幕和一组灯,用于显示电梯的当前位置和方向,另外一些远程操控的面板也会显示出同样的信息。电梯并不关心这些东西。当它穿过(或者停在)某一层的时候,它会发出一个 floorChanged(int) 信号。或许,交通信号灯是更合适的一个例子。你也可以实现一个应用程序,其中每一个函数调用都是通过信号来触发的。这在技术上说是完全没有问题的,然而却是不大可行的,因为信号槽的使用无疑会丧失一部分代码可读性和系统性能。如何在这其中做出平衡,也是你需要考虑的很重要的一点。Qt 方式了解 Qt 信号槽最好的莫过于 Qt 的文档。不过,这里我们从一个小例子来了解信号槽的 Qt 方式的使用。// Qt Signals and Slotsclass Button :public QObject{ & &Q_OBJECTQ_SIGNALS:void clicked();};class Page :public QObject{ & &Q_OBJECTpublic Q_SLOTS:void reload();};// given pointers to an actual Button and Page:connect(button,SIGNAL(clicked()), page, SLOT(reload()));Boost.Signals 方式了解 Boost.Signals 的最好方式同样是 Boost 的文档。这里,我们还是先从代码的角度了解一下它的使用。// Boost.Signalsclass Button{public: & &boost::signal&void()& clicked;};class Page{public:void reload();};// given pointers to an actual Button and Page:button-&clicked.connect( boost::bind(&Page::reload, page));对比或许你已经注意到上面的例子中,无论是 Qt 的实现方式还是 Boost 的实现方式,除了必须的 Button 和 Page 两个类之外,都不需要额外的类。两种实现都解决了类爆炸的问题。下面让我们对照着来看一下我们前面的分析。现在我们有:两个不同的术语以及各自的动作:信号和槽;在一个地方(信号)可以连接零个或者多个回调函数(槽),同时也是多对多的;焦点在于连接本身,而不是提供者或者消费者;不需要手工为了一个连接创建新的类;连接仍旧是类型安全的。这五点是信号槽系统的核心,Qt 和 boost 都拥有这些特性。下面则是二者的不同之处: Boost.Signals Qt Signals 和 Slots 一个信号就是一个对象 信号只能是成员函数发出信号类似于函数调用 发出信号类似于函数调用,Qt 提供了一个 emit 关键字来完成这个操作信号可以是全局的、局部的或者是成员对象 信号只能是成员函数 任何能够访问到信号对象的代码都可以发出信号 只有信号的拥有者才能发出信号 槽是任何可被调用的函数或者函数对象 槽是经过特别设计的成员函数 可以有返回值,返回值可以在多个槽中使用 没有返回值 同步的 同步的或者队列的 非线程安全 线程安全,可以跨线程使用 当且仅当槽是可追踪的时候,槽被销毁时,连接自动断开 槽被销毁时,连接都会自动断开(因为所有槽都是可追踪的) 类型安全(编译器检查) 类型安全(运行期检查) 参数列表必须完全一致 槽可以忽略信号中多余的参数 信号、槽可以是模板 信号、槽不能是模板 C++ 直接实现 &通过由 moc 生成的元对象实现(moc 以及元对象系统都是 C++ 直接实现的) &没有内省机制 可以通过内省发现 可以通过元对象调用 连接可以从资源文件中自动推断出最重要的是,Qt 的信号槽机制已经深深地植入到框架之中,成为不可分割的一部分。它们可以使用 Qt 专门的开发工具,例如 QtCreator,通过拖拽的方式很轻松的创建、删除、修改。它们甚至可以通过动态加载资源文件,由特定命名的对象自动动态生成。这些都是 boost 作为一个通用库所不可能提供的。
了这篇文章
类别:未分类┆阅读(0)┆评论(0)3823人阅读
编程语言 / C++(21)
如何使用BOOST
信号与插槽-概念
represents callbacks with multiple targets, and are also called publisher or
events in similar systems.
Signals are connected to some set of slots,
which are callback receivers(also called event targets or subscribers), which
are called when the signal is &emitted.&
: call a single slot.
&boost/signal.hpp&
&boost/thread/thread.hpp&
&boost/date_time/posix_time/posix_time.hpp&
&iostream&
Hello_World
()() const
wcout && & Hello World &
boost::signal&void
boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
sig.connect(hw);
:call multiple slots.
&boost/signal.hpp&
&boost/thread/thread.hpp&
&boost/date_time/posix_time/posix_time.hpp&
&iostream&
()() const
cout && & HELLO &
()() const
cout && & World &
boost::signal&void
sig.connect(1, world);
// Ordering slot call groups.
sig.connect(0, hello);
boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
Exp 3: how signals
arguments to each of the slots they call.
&boost/signal.hpp&
&boost/thread/thread.hpp&
&boost/date_time/posix_time/posix_time.hpp&
&iostream&
print_sum(float
std::cout && &The sum is &
print_product(float
std::cout && &The product is &
print_difference(float
std::cout && &The difference is &
print_quotient(float
std::cout && &The quotient is &
boost::signal&float
sig.connect(0, &print_sum);
sig.connect(1,
&print_product);
sig.connect(2,
&print_difference);
sig.connect(3,
&print_quotient);
// Output 1.6667 because return by
the last slot called.
cout && sig(5, 3) &&
Exp 4: return a maximum result by provide another argument.
&boost/signal.hpp&
&boost/thread/thread.hpp&
&boost/date_time/posix_time/posix_time.hpp&
&iostream&
print_sum(float
std::cout && &The sum is &
print_product(float
std::cout && &The product is &
print_difference(float
std::cout && &The difference is &
print_quotient(float
std::cout && &The quotient is &
InputIterator&
T operator
()(InputIterator
first, InputIterator last) const
( first == last )
T max_value = *first++;
( first != last )
( max_value & *first )
max_value = *
// installing Maximum as a
combiner for our signal.
boost::signal& float
), Maximum&float
sig.connect(0, &print_sum);
sig.connect(1,
&print_product);
sig.connect(2,
&print_difference);
sig.connect(3,
&print_quotient);
// Output 15.
cout && sig(5, 3) &&
return all of the values computed by the slots together, in one large
data structure.
&boost/signal.hpp&
&boost/thread/thread.hpp&
&boost/date_time/posix_time/posix_time.hpp&
&iostream&
print_sum(float
std::cout && &The sum is &
print_product(float
std::cout && &The product is &
print_difference(float
std::cout && &The difference is &
print_quotient(float
std::cout && &The quotient is &
InputIterator&
T operator
()(InputIterator
first, InputIterator last) const
( first == last )
T max_value = *first++;
( first != last )
( max_value & *first )
max_value = *
Container&
aggregate_values
Container result_
InputIterator&
Container operator
()(InputIterator
first, InputIterator last) const
Container(first, last);
boost::signal& float
aggregate_values&
std::vector&float
sig.connect(0, &print_sum);
sig.connect(1,
&print_product);
sig.connect(2,
&print_difference);
sig.connect(3,
&print_quotient);
std::vector&float
& results = sig(5, 3);
// Output 8 15 2 1.66667
std::copy(results.begin(),
results.end(),
std::ostream_iterator&float
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:85700次
积分:1066
积分:1066
排名:千里之外
原创:17篇
评论:10条
(1)(1)(1)(1)(2)(5)(15)

我要回帖

更多关于 如何使用boost库 的文章

 

随机推荐