Boost Event Management Architecture: Signal/slot (lower)

Source: Internet
Author: User
Tags emit

Original: http://viml.nchc.org.tw/blog/paper_info.php? Class_id = 1 & sub_id = 1 & paper_id = 229

For the signals2 function of boost, I explained it in the first article, and listed some of the most simple usage scenarios; in the second article
The slot's sequential control and zookeeper management are further explained.

In this article, we will give some explanations on how signal/slot operates on objects, as well as automatic scaling management.

Scoped connection

First, in signals2, boost provides
Boost: signals2: scoped_connection. You can control the signal/slot limit through the existence or absence of the object of this type; its basic usage is roughly as follows:

// include STL headers#include <stdlib.h>#include <iostream>// include Boost header#include <boost/signals2/signal.hpp>// slot functionvoid slotFunc1(){ std::cout << "Function 1" << std::endl; }void slotFunc2(){ std::cout << "Function 2" << std::endl; }int main( int argc, char** argv ){  // create a signal  boost::signals2::signal<void () > mSignal1;  {    boost::signals2::scoped_connection sc( mSignal1.connect( slotFunc1 ) );    mSignal1.connect( slotFunc2 );    // emit the signal    std::cout << "EMIT first time" << std::endl;    mSignal1();  }  // emit the signal  std::cout << "EMIT second time" << std::endl;  mSignal1();  return 0;}

In the above example, msignal1 is connected
Slotfunc1 () and
Slotfunc2 () slots.
When slotfunc1 () is used
The connection is passed to the type. Others are
Scoped_connection object
SC for Management (his usage is basically the same as previously mentioned
Shared_connection_block ). After such a setting, msignal1 and
The reason between slotfunc1 () becomes
SC controls the object.

Scoped_connection does not belong to the original
Connection, so it can be passed through
SC
Disconnect () function is used to initiate a temporary upload; however, scoped_connection indicates that the temporary upload automatically changes when its object disappears.

Therefore, the above program runs in the scope at the bottom of the program.
Msignal1 (), because
SC still exists, so
Slotfunc1 () and
Both slotfunc2 () slots are merged. However, after an external scope is created
SC has disappeared, so
Msignal1 and
The connections between slotfunc1 () are also in progress.
Msignal1 (), only the rows
Slotfunc2. In practice, the above program will be:

EMIT first timeFunction 1Function 2EMIT second timeFunction 2

In this way, we have passed through
Scoped_connection object exists and does not, to control the unique and most simple application of signal/slot parallel objects, just like its name, it becomes the limit bound by scope.

To a certain extent, if you can further control the existence and absence of this object, it can also be considered as one of the methods for managing the entire object. But in reality, scoped_connection's design is not used for auto-dynamic snapshot management, so it is more difficult to operate, you also need to perform external management.
Scoped_connection objects. This type is not copyable and cannot be copied. Therefore, there are many restrictions on use.

 

Use a similar operator form as a slot

Although scoped_connection may be able to perform automatic zookeeper management to some extent, in practice, signals2 has a zookeeper method, it can be used to manage the links of signal/slot by the existence of an animation root object. However, before performing automatic scaling, we must first mention how to use a member function as a slot function.

To do this, the most direct and common method is to pass through tr1 directly.
BIND () (member 1), which encapsulates the employee form of the object into a funciton object, and then sends it
Signal: connect (); related
This part of BIND () is not the main topic here, for more information, see section 3: function object in tr1 in C ++.

In the following example, one is used in the signal/slot.
BIND () ticket example:

// include STL headers#include <stdlib.h>#include <iostream>#include <complex>// include Boost header#include <boost/signals2/signal.hpp>// the class with slot functionclass CObject{public:  int  m_ObjIndex;  CObject( int idx )  {    m_ObjIndex  = idx;  }  void slotFunc()  {    std::cout << "Object " << m_ObjIndex << std::endl;  }};int main( int argc, char** argv ){  // create signal  typedef boost::signals2::signal<void ()> TSignalType;  TSignalType  mSignal;  // create object  CObject  *pObj1 = new CObject( 1 );  // connect signal /slot  mSignal.connect( std::bind( &CObject::slotFunc, pObj1 ) );  // emit signal  mSignal();  return 0;}

In the previous program, the first thing is to define
Except for cobject, there is only one operator that records the changes of its own index, the constructor, And the cobject operator.
Slotfunc ().

In the main program, a signal object is created first, but it is passed through first.
Typedef defines the signal type as tsignaltype, which can be used to compile the Program program later. Then,
Cobject objects
Pobj1, and through
Signal: connect () to set up its membership form
Slotfunc () and
The msignal performs the termination. In terms of usage, STD: BIND () is used to package the program validation method, which is the bottom part of the above; if the signal/slot has external memory, you need to add placeholder.
STD: BIND () is not mentioned here.

Besides tr1
BIND () can package the operator form of an object into a function object. In fact, signals2 also provides another scheme to convert the object into a member form, except for the corresponding slot function type. His method is:

TSignalType::slot_type( &CObject::slotFunc, pObj1 )

In practice, slot_type is the type of slot function used by signals2 for configuring and configuring the corresponding signal. Signal: connect ()
The slot function that needs to be merged is actually this type. In general, when using the function compute, the function compute object will be automatically converted
Slot_type; in this example, it is the external construction method, which manually organizes the object
Slot_type object.

In this way, the program connected by signal and slot will become:

mSignal.connect( TSignalType::slot_type( &CObject::slotFunc, pObj1 ) );

This method is similar to the above
STD: BIND () method. The result is basically the same. In reality, in terms of interface and usage, it is consistent with tr1.
BIND () is also the same (in fact, the internal part of the response should be called
BIND.

 

Automatic renewal Management

When using an employee's function as a slot, the biggest problem is that, even if the object disappears, signal is released, still, the operator of an object that has already been deleted will fail to parse the code, which may cause a program issue. For example, in the preceding example
If pobj1 is deleted, the result of the line "msignal ();" will be a problem, is a program with issues:

// connect signal /slotmSignal.connect( TSignalType::slot_type( &CObject::slotFunc, pObj1 ) );// emit signaldelete pObj1;mSignal();

How can we avoid this problem? Signals2 provides
Track () function, so that it can be used with boost
Shared_ptr (audit file; example 2) is used to track the existence of a specified object and confirm that it is the result of controlling the signal/slot. The following is an example of the statement modified by the Program on the root node:

// create signaltypedef boost::signals2::signal<void ()> TSignalType;TSignalType  mSignal;// create objectCObject  *pObj1 = new CObject( 1 );// connect signal /slot{  boost::shared_ptr<CObject> spObj( pObj1 );  mSignal.connect( TSignalType::slot_type( &CObject::slotFunc, spObj.get() ).track( spObj ) );  // emit signal  mSignal();}// emit signalmSignal();

In this program, after entering the bottom scope, the cobject object
Pobj1 will be changed to use
Spobj
Boost: The shared_ptr type is used to manage other objects. shared_ptr is very similar to the standard. However, it will remember that
Number of pobj1 objects
Shared_ptr is used. If none of them exist, it will automatically
Pobj1 removes the memory and avoids memory leak. Only
Spobj is used by an entity.
Pobj1, so when the external scope is opened and you want to disappear
The information of pobj1 is also removed, which is equivalent to the actual operation.
Delete pobj1.

In order to avoid the removal of pobj1, msingal will continue to perform other operations.
Slotfunc ().
The time for slot_type objects is also passed through
Slot_type
Track (), let him catch up
Spobj. In this case, the spobj itself disappears after the scope at the bottom is opened.
The same time of pobj1 resources will also be automatically switched
Msignal and
Pobj1-> slotfunc.

Therefore, when the above program crashes "msignal ();" for the first time, it will call
Pobj1-> slotfunc (); but when the second row is "msignal ();" (outside the scope of the bottom), it is caused
Msignal and
The result between pobj1-> slotfunc () has been automatically switched.
Pobj1-> slotfunc ()

In this way, the lifecycle of the root object can be automatically determined by the signal/slot encoding and no functions, in this way, you can avoid calling the function of the deleted object. However, in contrast, such a deficiency is that an object must be used.
Boost: shared_ptr, an object managed by an automatic resource, is dead... So whether or not you want to use it like this is probably because you have to retrieve the token yourself.

In addition, track () stores the objects to be traced in the form of a clear list. Therefore, if necessary, you can call them through retries.
Track (), to catch up with multiple objects at the same time, and as long as one of the objects disappears, the program will be in progress. In addition, the actual
Track () can also be used to catch up with other signal and other slots (slot 3), but heresy is not very proud, so I will not mention it here. If you are interested, you can refer to the official documents (website) for further explanation.

 

For the introduction of boost signals2, it is probably the first time. In fact, he also has some external progressive usage (especially thread-related), but in this case, he will not mention it first, and there are people who need it, let's take a look at the official documents.

Appendix:
  1. If the zookeeper does not support tr1, you can also use boost bind. In practice, the official example of boost is the BIND of boost.
  2. Track () is actually used
    Obtained by shared_ptr
    Weak_ptr, avoid
    The calculator in shared_ptr calculates this part as well. In addition, although tr1 already has
    Shared_ptr is used, but it is caused by unfeasible and boost versions, so only boost versions can be used here.
  3. When track () is used to catch up with the slot, in fact, it is used to catch up with "the objects that the slot is chasing 」, instead of the specified slot, the slot itself is chased. That is, when the rows
    Slot1.track (slot2); When slot1 is used, slot1 will catch up with others.
    Slot2 has objects that are being chased, but it will not be used to catch up
    Slot2 itself.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.