Boost::Signals2 学习

  Boost::Signals和Signals2的区别是Signals2是现成安全的;信号和插槽的核心目的是降低各个模块的耦合性
first,we create a signal sig, a signal that takes no arguments and has a void return value.Next, we connect the hello function object to the signal using the connect method. Finally, use the signal sig like a function to call the slots, which in turns invokes HelloWorld::operator() to print "Hello,World". 

 1 struct HelloWorld {
2 void operator()() const {
3 std::cout << "Hello, World" << std::endl;
4 }
5 };
6
7
8 int main(int argc, char* argv[])
9 {
10 boost::signals2::signal<void ()> sig;
11 HelloWorld hello;
12 sig.connect(hello);
13 sig();
14 }

   

  Connecting Multiple slots

 1 struct Hello {
2 void operator()() const {
3 std::cout << "Hello";
4 }
5 };
6
7 struct World {
8 void operator()() const {
9 std::cout << ",World" << std::endl;
10 }
11 };
12
13 int main(int argc, char* argv[])
14 {
15 boost::signals2::signal<void ()> sig;
16 sig.connect(Hello());
17 sig.connect(World());
18 sig();
19 }

  

  Ordering Slots Clall Groups
Slots are free to have side effects, and that can mean that some slots will have to be called before others even if they are not connected in that orde.The Boost.Signals2 library allows slots to be placed into groups that are ordered in some way. For our Hello,World program,we want "Hello" to be printed before ", World!", so we put "Hello" into a group that must be executed before the group that ", World!" is in. To do this, we can supply an extra parameter at the beginning of the connect call that specifies the group. Group values are, by default, ints, and are ordered by integer < relation.

1     sig.connect(1, World());
2 sig.connect(0, Hello());

  

  Mix ordering slots with default slots

1 struct GoodMorning {
2 void operator()() const {
3 std::cout << "... and good morning!" << std::endl;
4 }
5 };
6
7 sig.connect(GoodMorning()); // default to the end of the list

and how to make GoodMorning at front of the ordering slots?

sig.connect(GoodMorning(), boost::signals2::at_front);// passing boost::signals2::at_front or boost::signals2::at_back as the last parameter to connect, resp                               // ectively

slots are invoked this order:
1) ungrouped slots connected with boost::signals2::at_front
2) grouped slots according to ordering of their groups
3) ungrouped slots connected with boost::signals2::at_back 

  Passing Values to and from Slots
   Signals can progagate(传送) arguments to each of the slots they call.

 1 void print_ars(float x, float y) {
2 std::cout << "The arguments are " << x << " and " << y << std::endl;
3 }
 4 
5 int main(int argc, char* argv[])
6 {
7 boost::signals2::signal<void (float, float)> sig;
8 sig.connect(print_ars);// 文档中用的是 sig.connect(&print_args) 我不解 print_args本身不就是地址吗;
9 sig(5., 3.);// 如果connect了多个slot 则依次执行 slot(函数)
10 }

  

  Signals Return Values:看到boost::signals2::signal<void (float, float)> sig;括号中(float, float)指传入的参数,void是返回值类型。

 1 float print_ars(float x, float y) {
2 std::cout << "The arguments are " << x << " and " << y << std::endl;
3 return x + y;
4 }
5
6 float difference(float x, float y) {
7 return x - y;
8 }
9 int main(int argc, char* argv[])
10 {
11 boost::signals2::signal<float (float, float)> sig;
12 sig.connect(print_ars); // 文档中用的是sig.connect(&print_args);
13 sig.connect(difference);
14 std::cout << *sig(5., 3.) << std::endl;
15 }

return a boost::optional containing the result returned by the last slot called.
  

  Add a combiner 

 1 template<typename T>
2 struct maximum
3 {
4 typedef T result_type;
5
6 template<typename InputIterator>
7 T operator()(InputIterator first, InputIterator last) const
8 {
9 // If there are no slots to call, just return the
10 // default-constructed value
11 if(first == last ) return T();
12 T max_value = *first++;
13 while (first != last) {
14 if (max_value < *first)
15 max_value = *first;
16 ++first;
17 }
18
19 return max_value;
20 }
21 };
22
23 int main(int argc, char* argv[])
24 {
25 boost::signals2::signal<float (float, float), maximum<float >> sig;
26 sig.connect(print_ars); // 文档中用的是sig.connect(&print_args);
27 sig.connect(difference);
28 std::cout << sig(5., 3.) << std::endl;
29 }

result returned by the maximum value called by print_args & difference.

  Disconnectiong Slots
  Slots arenot expected to exist indefinitely(不确定地) after they are connected.Often slots are only used to receive a few events and are then disconnected, and the programer needs control to decide when a slot should no longer be connected.
  The entry point for managing connections explicitly is the boost::signals2::connection class. The connection class uniquely represents the connection between a particular signal and a particular slot.The connected() method checks if the signal and slots are still connected ,and the disconnect() method disconnects the signal and slot if they are connected before it is called. Each call to the signal’s connect() method returns a connection object,which can be used to determine if the conneciton still exists or to disconnect the signal and slot.

1 boost::signals2::connection c = sig.connect(Hello());
2 sig();
3 c.disconnect();
4 sig();


  Blocking(阻塞) Slots
  
Slots can be temporarily "blocked", meaning that they will be ignored when the signal is invoked but have not been permanently disconnected. This is typically used to prevent infinite recursion in cases where otherwise running a slot would cause the signal it is connected to be invoked again.A boost::signals2::shared_connection_block object will temporarily block a slot. The connection is unblocked by either destroying or calling unblock on all the shared_connection_block object that reference the connection. Here is an example of blocking/unblocking slots:

1 boost::signals2::connection c = sig.connect(Hello());
2 sig();
3 {
4 boost::signals2::shared_connection_block block(c);
5 std::cout << "c is blocked.\n";
6 sig();
7 }
8 std::cout << "c is not blocked \n";
9 sig();


  Scoped Connections 
  The boost::signals2::scoped_connection class references a signal/slot connection that will be disconnected when the scoped_connection class goes out of scope. This ability is useful when a connection need only be temporary.

1 boost::signals2::signal<void ()> sig;
2 {
3 boost::signals2::scoped_connection c = sig.connect(Hello());
4 sig();
5 }
6 sig();

note, attempts to initialize a scoped_connection with the assignment syntax will fail due to it being noncopyable. Either the explicit initializaion syntax or default construction followed by assignment from a signals2::connection will work:
照这个说的我上述程序本来应该编译不过的,可是它就是编译过了。(是不是connect现在是copyalbe了?)

  Disconnectiong Equivalent Slots
  One can disconnect slots that are equivalent to a given function object using a form of the signal::disconnect method, so long as the type of the function object has an accessible == operator.

 1 void foo() {
2 std::cout << "foo";
3 }
4
5 void bar() {
6 std::cout << "bar\n";
7 }
8
9 int main(int argc, char* argv[])
10 {
11 boost::signals2::signal<void ()> sig;
12 sig.connect(foo);// 文档中是sig.connect(&foo);
13 sig.connect(bar);
14 sig();
15
16 sig.disconnect(foo);
17 sig();
18 }


  Automatic Connection Management 
// 目前只简单了解下 没深刻理解
  
boost::Signals2 can automatically track the lifetime of objects involved in signal/slot connection, including automatic disconnection of slots when objects involved in the slot call are destroyed.For instance, consider a simple news delivery service, where clients connect to a news provider that then sends news to all connected clients as information arrives. (观察者模式)The news delivery service may be constructed like this:
  However, What if the user closes the news message area, destroying the newsMessageArea object that deliverNews knows about? Most likely, a segmentation fault will occur. However, whith Boost.Signals2 one may track any object which is managed by a shared_ptr, by using slot::track. A slot will automatically disconnect when any of its tracked objects expire(过期). In addition, Boost.Signals2 will ensure that no tracked object expires while the slot it is associated with is in mid-execution. It does so by creating temporary shared_ptr copies of the slot's tracked objects before executing it. To track NewsMessageArea, we use a shared_ptr to manage its lifetime, and pass the shared_ptr to the slot via its slot::track method before connecting it.

  When Can Disconnections Occur?
  1.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.
  2.An object tracked by the slot is destroyed.
  3.The signal is destroyed. 

  Passing Slots // 简单看一下
  Slots in the Boost.Signals2 library are created from arbitrary 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 slot_type for each particular signal type and any function object compatible with the signal can be passed to a slot_type parameter. 

  就看到这里吧!下面还有Giving a Slot Access to its Connection&Changing the Mutex Type of a Signal暂时看到这里,前面还有许多概念没理解清楚,回过头来看一下吧!


  Slot && Signal,许多Slot可以注册一个Signal,只要Signal被执行就可以调用所有Slot的的operator();在以后用到时要多考虑一下,用这种方法解耦的好处。看书的时候,一些点看不懂没关系,看完时回过头再看就有个更清晰的认识;过段时间再想,理解的会更深刻,哪怕先前理解错了。

write by fgd

posted @ 2011-11-30 13:14  wen_dao_  阅读(5438)  评论(0编辑  收藏  举报