信号插槽系统中的线程安全性(C ++ 11)

时间:2017-02-01 09:09:28

标签: multithreading c++11 signals slot

我在使用C ++ 11设计信号/插槽系统时遇到了一些问题。

我的主要设计目标是:简单但仍然提供一些功能和线程安全。 我对信号/插槽系统的个人意见是发射应该尽可能快。因此,我试图将信号列表保持在信号整齐。许多其他信号/插槽系统将断开的插槽留空。这意味着在信号发射期间需要更多的时隙来迭代和检查时隙有效性。

以下是具体问题:

信号类具有一个发射功能和一个用于断开插槽的功能:

template<typename... Args>
void Signal<void(Args...)>::operator()(Args&&... args)
{
    std::lock_guard<std::mutex> mutex_lock(_mutex);

    for (auto const& slot : _slots) {
        if (slot.connection_data->enabled) {
            slot.callback(std::forward<Args>(args)...);
        }
    }
}

template<typename... Args>
void Signal<void(Args...)>::destroy_connection(std::shared_ptr<Connection::Data> connection_data)
{
    std::lock_guard<std::mutex> mutex_lock(_mutex);

    connection_data->reset();

    for (auto it = _slots.begin(); it != _slots.end(); ++it) {
        if (it->connection_data == connection_data) {
            *it = _slots.back(); _slots.pop_back();
            break;
        }
    }
}

这可以正常工作,直到有人试图建立一个在发出信号时断开连接的连接:

Connection con;
Signal<void()> sig;

con = sig.connect([&]() { con.disconnect(); });
sig();

我有两个问题:

  1. 必须重新设计emit函数,因为迭代时可能会删除插槽。
  2. 同一个帖子中有两个互斥锁。
  3. 是否有可能使这项工作(可能使用递归互斥?),或者我应该重新设计系统以不干扰插槽列表并在断开信号时留下空插槽(正如许多其他类似项目那样)?

0 个答案:

没有答案