提升1.49条件变量问题

时间:2014-03-14 23:39:26

标签: multithreading c++11 boost-thread

我正在尝试在我的应用程序中使用Boost Conditional变量来同步两个不同的线程,如下所示:

主线程将创建一个名为MIH-User的TCP服务器和对象实例,并向event_handler注册一个回调。

Main.cpp的

/**
* Default MIH event handler.
*
* @param msg Received message.
* @param ec Error code.
*/
void event_handler(odtone::mih::message &msg, const boost::system::error_code &ec)
{
if (ec)
{
    log_(0, __FUNCTION__, " error: ", ec.message());
    return;
}

switch (msg.mid())
{
    // Source Server received HO Complete Message
    case odtone::mih::indication::n2n_ho_complete:
    {
        if (ec)
        {
            log_(0, __FUNCTION__, " error: ", ec.message());
            return;
        }

        mih::id             mobile_id;          // Mobile node MIHF ID TLV
        mih::link_tuple_id  source_id;          // Source Link ID TLV
        mih::link_tuple_id  target_id;          // Target Link ID TLV
        mih::ho_result      ho_res;             // Handover Result TLV

        // Deserialize received MIH message "N2N Handover Complete Indication"
        msg >> mih::indication()
            & mih::tlv_mobile_node_mihf_id(mobile_id)
            & mih::tlv_link_identifier(source_id)
            & mih::tlv_new_link_identifier(target_id)
            & mih::tlv_ho_result(ho_res);

        log_(0, "has received a N2N_HO_Complete.Indication with HO-Result=", ho_res.get(), 
            " from ", msg.source().to_string(), ", for Mobile-IP=", mobile_id.to_string());

        // Find the source transaction which corresponds to this Indication
        src_transaction_ptr t;
        tpool->find(msg.source(), mobile_id.to_string(), t);
        {
            boost::lock_guard<boost::mutex> lock(t->mut);
            t->response_received = true;
            t->ho_complete_result = ho_res;
            t->tid = msg.tid();
        }
        t->cond.notify_one();
    }
    break;

}

}

int main(int argc, char **argv)
{
        odtone::setup_crash_handler();
        boost::asio::io_service ios;

    sap::user usr(cfg, ios, boost::bind(&event_handler, _1, _2));
    mMihf = &usr;

    // Register the MIH-Usr with the local MIHF
    register_mih_user(cfg);

    // Pool of pending transactions with peer mihfs
    ho_transaction_pool pool(ios);
    tpool = &pool;

    // The io_service object provides I/O services, such as sockets, 
    // that the server object will use.
    tcp_server server(ios, cfg.get<ushort>(kConf_Server_Port));
}

TCP服务器将侦听新的传入连接,并且在接收到新连接时,它将创建与源事务计算机相对应的新线程,并将它添加到公共事务池,如下所示:

TCP服务器

void handle_request(std::string arg1,std::string arg2)
{
    src_transaction_ptr t(new src_transaction(arg1, arg2));
    tpool->add(t);
    t->run();
}

void handle_read(const boost::system::error_code &error, size_t bytes_transferred)
{
    if (!error)
    {
        // Split received message defining ";" as a delimiter
        std::vector<std::string> strs;
        boost::split(strs, mMessage, boost::is_any_of(":"));
        log_(0, "Received Message from TCP Client: ", mMessage);

        // The first value is the HO Command Initiation message
        if ((strs.at(0).compare("INIT") == 0) && (strs.size() == 3))
        {
            // The second value is the MIHF ID and the third is the IP address
            // Start Source transaction if we receive "Init-Message"
            boost::thread thrd(&tcp_connection::handle_request, this, strs.at(1), strs.at(2));
        }
        else if ((strs.at(0).compare("TEST") == 0) && (strs.size() == 3))
        {
            int max_iterations = atoi(strs.at(2).c_str());
            for (int i = 1; i <= max_iterations; i++)
            {
                boost::thread thrd(&tcp_connection::handle_request,
                    this, strs.at(1), boost::lexical_cast<std::string>(i));
            }
        }
        else
            log_(0, "Error: Unrecognized message.");

        memset(&mMessage[0], 0, max_length);

        mSocket.async_read_some(boost::asio::buffer(mMessage, max_length),
            boost::bind(&tcp_connection::handle_read, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

    }
}

源事务机器将在不同的状态之间移动,并且在其中一个状态中,它必须冻结执行,直到它通过主线程接收到此时为“n2n_ho_complete”的指示,它将设置response_received为如下:

来源交易机

/**
* Run Source State Machine transaction.
*/
void src_transaction::run()
{        
// Previuos states.

wait_ho_complete_indication_state:
{
    log_(1, "is in SRC_WAIT_HO_COMPLETE_INDICATION State for Mobile IP=", ip_address);
    mState = SRC_WAIT_HO_COMPLETE_INDICATION;

    boost::unique_lock<boost::mutex> lock(mut);
    while (!response_received)
    {
        cond.wait(lock);
    }

    response_received = false;

    // Do some stuff
}

    // Other states

return;

}

response_received是一个公共变量,该类的每个实例都有自己的变量。当通过主线程接收到指示时,它将查找与该指示匹配的源事务,并将其response_received设置为true。

所以我的问题是:每当我尝试执行代码时,整个程序都会挂起wait_ho_complete_indication_state,程序不会响应任何内容。 例如,如果我请求为源事务创建10个线程。程序将创建所有这些程序并且它们开始同时工作,直到其中一个到达wait_ho_complete_indication_state,然后一切都冻结。即使主线程完全没有响应,即使它通过event_handler接收到指示。

我的代码使用条件变量是否正确?

请帮助解决这个问题。

非常感谢。

0 个答案:

没有答案