【问题标题】:Handle connection/disconnection of many signals/slots with boost::signals2使用 boost::signals2 处理许多信号/插槽的连接/断开
【发布时间】:2011-06-07 13:19:07
【问题描述】:

我已经开始使用 boost::signals2 而不是我的旧信号代码。不过,我在管理多个连接时遇到了问题。这是我的问题:

我有很多 Person 类的实例:

class Person {
public:
    void SetName (string new_name)
    {
        name = new_name;
        NameChange (name);
    }

    string name;
    boost::signals2::signal<Person*> NameChange;
};

我还有一个人员浏览器,它必须监视所有可用人员的子集以进行更改。由于人们可以从该子集进出,我必须有一种方法来处理连接对象,并且我创建了一个类 (ConnectionList) 来处理它:

class ConnectionList
{
public:
    virtual ~ConnectionList () // drops all connections in "list"
    void add (boost::signals2::connection& conn); // adds "conn" to "list"
private:
    std::vector<boost::signals2::connection> list;
};

class PeopleBrowser
{
public:
    void AddPerson (Person& p)
    {
        name_change_connections.add (p.NameChange.connect (...));
    }
private:
    ConnectionList name_change_connections;
};

这一切都很好,删除 PeopleBrowser 时连接会被删除,并且有一种添加新连接的好方法。

但是,我们需要添加另一个方法 RemovePerson,并且该方法必须删除与该 Person 实例的 NameChange 信号的连接。

这就是我卡住的地方。我想我可以让 ConnectionList 成为一个模板,并使用一个包含一个结构体的列表,该结构体引用了信号和连接,然后添加一个方法来删除与该信号的所有连接。

但似乎这是一个很常见的情况(至少在我的世界里,我在这个单一的应用程序中有 20 个类需要这个功能),所以我认为必须有更好的方法来处理这个问题?

至少,有没有办法从连接对象中获取对连接信号的引用?

也许 libsigc++ 可以更好/不同地处理这个问题?

【问题讨论】:

    标签: c++ boost signals boost-signals2


    【解决方案1】:

    怎么样:

    class PeopleBrowser
    {
    public:
        void AddPerson (Person& p)
        {
            name_change_connections[&p] = p.NameChange.connect(...);
        }
        void RemovePerson(Person& p)
        {
             name_change_connections.erase(&p);
        }
    
    private:
        std::map<Person*, boost::signals2::scoped_connection> name_change_connections;
    };
    

    您可能还想看看automatic connection management

    【讨论】:

    • 您是否还需要添加一个disconnect 方法调用,以便在将信号/槽关系从地图中删除之前实际断开它?还是会自动发生(即在boost::signals2::connection 对象的析构函数中处理)?
    • 你应该使用 scoped_connection。
    • 谢谢,我现在非常像这样实现它,除了没有 scoped_connection 的复制构造函数,所以我仍然有我的 ConnectionList 类,它在销毁时断开并删除所有连接。完成一些测试后,我会更新我的问题。
    【解决方案2】:

    我自己没试过,但根据boost documentation

    什么时候会出现断线? (中级)

    当出现以下任何一种情况时,就会发生信号/插槽断开:

    • 直接通过连接的disconnect 方法或通过信号的disconnect 方法或scoped_connection 的析构函数间接显式断开连接。
    • 槽跟踪的对象被销毁。
    • 信号被破坏。

    除非您使用scoped_connection,否则信号和插槽之间的连接将保持有效,直到其中任何一个被破坏。据我了解,您不需要将连接对象存储在向量中。只需像现在一样将信号连接到插槽即可。

    当您观察到的对象超出范围时,它会自行删除连接。

    这是一个更简单的设计。

    【讨论】:

    • 连接对象本身会占用一些内存,即使断开连接也是如此。因此,如果信号被破坏,连接对象将设置为断开连接,但不会被释放。当 PeopleBrowser 被销毁时,它的所有连接对象都将被释放,但 PeopleBrowser 可能会长期存在(在这种情况下是整个进程的生命周期)。而且信号并不总是被破坏,可能是 PersonBrowser 不再关心那个特定的人,不应该再从它那里接收任何信号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多