class WIFITest
{
public:
void StartTest();
void Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id );
private:
void OpenStaMode_test();
private:
boost::shared_ptr<boost::thread> OpenStaMode_testThread;
boost::shared_ptr<basic_msg> VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG;
typedef boost::shared_ptr<boost::thread> THREAD;
typedef boost::shared_ptr<basic_msg> MSG;
std::map<ID,std::pair<THREAD,MSG>> map;
};
void WIFITest::StartTest()
{
map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(OpenStaMode_testThread,VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);
this->OpenStaMode_testThread.reset(new boost::thread(&WIFITest::OpenStaMode_test,this));
this->OpenStaMode_testThread->join();
}
void WIFITest::OpenStaMode_test()
{
unsigned char strData[WIFI_SEND_BUF_SIZE_MIN];
sendOpenReq(strData);
try {
boost::this_thread::sleep(boost::posix_time::seconds(8));
}
catch(const boost::thread_interrupted&) {
std::cout<<"OpenStaMode_test success@ n";
}
else {
goto OpenStaMode_test_fail;
}
return;
}
OpenStaMode_test_fail:
printf("@WIFITest::OpenStaMode_test FAIL@@@@@@@@@@@@@@ n");
}
void WIFITest::Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id)
{
map[id].second = basic_msg;
map[id].first->interrupt();
printf("@WIFITest::INTERRUPTED @@@@@@@@@@@@@@ n");
}
第一个main将创建StartTest实例并调用StartTest(),当其他代码调用Notify_Test时,"map[id].first->interrupt();"这句话将产生以下断言失败,并使程序崩溃。
TestWIFI: ../../boost_1_55_0/boost/smart_ptr/shared_ptr.hpp:653: typename boost::detail::sp_member_access::type boost::shared_ptr::operator->() const [with T = boost::thread, typename boost::detail::sp_member_access::type = boost::thread*]:断言' px != 0'失败。
这一行:
map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(OpenStaMode_testThread,VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);
将OpenStaMode_testThread
的副本存储到映射中,此时该副本为空。
然后在OpenStaMode_testThread
上调用reset(new boost::thread(&WIFITestSuite::OpenStaMode_test,this))
,但这并不影响已经存储到映射中的副本。
因此,当您调用map[id].first->interrupt();
时,您是在一个空的shared_ptr
上调用它,从而导致断言失败。
如下所述,如果调用Notify_Test
可以在线程开始执行之后发生,但在shared_ptr
上的reset()
调用将其存储到映射中之前发生,则存在竞争条件。要解决这个问题,可以使用互斥锁:
class WIFITest
{
public:
/* ... */
private:
/* ... */
private:
boost::mutex mutex_;
/* ... */
};
void WIFITest::StartTest()
{
{
boost::lock_guard<boost::mutex> guard(mutex_); // Takes ownership of the mutex
map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(THREAD(), VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);
map[ID::WIFI_REQ_CLIENT_OPEN].first.reset(new boost::thread(&WIFITest::OpenStaMode_test,this));
// At this point the thread has started and the pointer has been stored into the map
} // guard is destructed and mutex released here
// so that we don't hold the mutex while waiting
// for the thread to finish.
map[ID::WIFI_REQ_CLIENT_OPEN].first->join();
}
/* ... */
void WIFITest::Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id)
{
boost::lock_guard<boost::mutex> guard(mutex_); // Takes ownership of the mutex
map[id].second = basic_msg;
map[id].first->interrupt();
printf("@WIFITest::INTERRUPTED @@@@@@@@@@@@@@ n");
}