Hello,
I am trying to use Boost Conditional variable in my application to synchronize two different threads as following:
The main thread, will create a TCP server and instance of object called MIH-User and register a callback to an event_handler.
Main.cpp
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())
{
case odtone::mih::indication::n2n_ho_complete:
{
if (ec)
{
log_(0, __FUNCTION__, " error: ", ec.message());
return;
}
mih::id mobile_id; mih::link_tuple_id source_id; mih::link_tuple_id target_id; mih::ho_result ho_res;
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());
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_mih_user(cfg);
ho_transaction_pool pool(ios);
tpool = &pool;
tcp_server server(ios, cfg.get<ushort>(kConf_Server_Port));
}
The TCP server will listen for new incoming connections and upon the reception of a new connection it will create a new thread corresponding to a source transaction machine also it will add it to a common transaction pool as following:
TCP Server
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)
{
std::vector<std::string> strs;
boost::split(strs, mMessage, boost::is_any_of(":"));
log_(0, "Received Message from TCP Client: ", mMessage);
if ((strs.at(0).compare("INIT") == 0) && (strs.size() == 3))
{
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));
}
}
The source transaction machine will move between different states and in one of the states it will have to freeze the execution until it receives an indication through the main thread which is the "n2n_ho_complete" at this time, it will set the response_received to ture as following:
Source Transaction Machine
void src_transaction::run()
{
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;
}
return;
}
The response_received is a public variable and each instance of the class has its own variable. When an indication is received through the main thread, it will look for the source transaction that matches that indication and sets its response_received to true.
So my problem is: whenever I try to execute the code, the whole program hangs on the wait_ho_complete_indication_state ,and the program doesn't respond to anything. And for example if I request the creation of a 10 threads for a source transaction. The program will create all of them and they start to work concurrently, until one of them reaches the wait_ho_complete_indication_state , then everything freezes. Even the main thread doesn't respond at all, even if it received an indication throught the event_handler.
So is my code correct for using the conditional variable?
Please help with this issue.
Thanks a lot.