#include "MsgThread.h" #include using namespace std; static mutex gs_mutex; static bool flag = false; bool MsgThread::MainLoop(void *p) { auto pThis = static_cast(p); while (true) { if (gs_mutex.try_lock()) { if (pThis->m_EventVec.size() != 0) { auto pObj = *(pThis->m_EventVec.begin()); dealMsg(pObj); pThis->m_EventVec.erase(pThis->m_EventVec.begin()); } gs_mutex.unlock(); } } return true; } MsgThread::MsgThread() { m_pThread = new thread(&MsgThread::MainLoop, this,this); m_pThread->detach(); } MsgThread* MsgThread::getInstance() { if (m_DataThread == NULL) { auto pDataThread = new MsgThread(); m_DataThread = pDataThread; } return m_DataThread; } void MsgThread::dealMsg(Message& _msg) { if (_msg._Selector == NULL) { _msg.pLayer->HandleMessage(_msg.pLayer, _msg.ret); return; } bool ret = (_msg.pLayer->*_msg._Selector)(_msg.pLayer); if (ret) { _msg.pLayer->HandleMessage(_msg.pLayer,_msg.ret); } else { _msg.pLayer->HandleMessage(_msg.pLayer,0); } } void MsgThread::sendMsg(Message _msg) { gs_mutex.lock(); m_EventVec.push_back(_msg); CCLOG("vec.size:%d",m_EventVec.size()); flag = true; gs_mutex.unlock(); } MsgThread* MsgThread::m_DataThread = NULL; ``` 我在MsgThread中实现了C++11的多线程,在mainloop 和sendmsg中加锁,但是好像死锁了,不知道要怎么搞请大神帮忙, mainloop中的while循环主要处理sendmsg函数添加的消息,我在UI线程里连续调用sendmsg函数5次,但是在mainloop中 只处理了一次,而且sendmsg函数打印m_EventVec的size也只有一个,求高人指点 没人帮我,昨天搞了一晚上,找到个原因,在mainloop中我调用CCLog函数,以下是cclog的源代码static void _log(const char *format, va_list args) { char buf; vsnprintf(buf, MAX_LOG_LENGTH-3, format, args); strcat(buf, "\n"); #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID __android_log_print(ANDROID_LOG_DEBUG, "cocos2d-x debug info", "%s", buf); #elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 WCHAR wszBuf = {0}; MultiByteToWideChar(CP_UTF8, 0, buf, -1, wszBuf, sizeof(wszBuf)); OutputDebugStringW(wszBuf); WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, buf, sizeof(buf), nullptr, FALSE); printf("%s", buf); SendLogToWindow(buf); fflush(stdout); #else // Linux, Mac, iOS, etc fprintf(stdout, "%s", buf); fflush(stdout); #endif Director::getInstance()->getConsole()->log(buf); } ``` 在cclog的源代码中会调用SendLogToWindow(buf)这个函数,一下是该函数源代码void SendLogToWindow(const char *log) { // Send data as a message COPYDATASTRUCT myCDS; myCDS.dwData = CCLOG_STRING_TAG; myCDS.cbData = (DWORD)strlen(log) + 1; myCDS.lpData = (PVOID)log; if (Director::getInstance()->getOpenGLView()) { HWND hwnd = Director::getInstance()->getOpenGLView()->getWin32Window(); SendMessage(hwnd, WM_COPYDATA, (WPARAM)(HWND)hwnd, (LPARAM)(LPVOID)&myCDS); } } ``` 在win32环境下,该函数会调用SendMessage函数,而这个函数是个阻塞函数,意味着 发送消息后,要等待主线程处理该消息,那么问题就来了,当我在mainloop中加上锁,该函数就会一直阻塞, 导致整个UI卡死,不加锁却不会阻塞,这里是我新的疑问,不明白sendmessage在加锁后为什么会阻塞, 而且这个问题也不固定,有时候会阻塞,有时候却不会阻塞,没辙了我把SendMessage改成postMessage了,
你用的哪个版本的cocos2dx引擎,我的是cocos2d-x-3.3rc0.
void _log函数中并没有调用SendLogToWindow函数,引擎中根本没有SendLogToWindow这个函数。
你可能用的是老版本的引擎,或者SendLogToWindow这个函数是你自己加进去的。
下面是cocos2d-x-3.3rc0版中的_log函数源码:
static void _log(const char *format, va_list args)
{
char buf;
vsnprintf(buf, MAX_LOG_LENGTH-3, format, args);
strcat(buf, "\n");
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
__android_log_print(ANDROID_LOG_DEBUG, “cocos2d-x debug info”, “%s”, buf);
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_WP8
WCHAR wszBuf = {0};
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wszBuf, sizeof(wszBuf));
OutputDebugStringW(wszBuf);
WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, buf, sizeof(buf), nullptr, FALSE);
printf("%s", buf);
fflush(stdout);
#else
// Linux, Mac, iOS, etc
fprintf(stdout, “cocos2d: %s”, buf);
fflush(stdout);
#endif
Director::getInstance()->getConsole()->log(buf);
}
函数里已经有了OutputDebugStringW,
再调用SendLogToWindow发送到窗口显示没有必要。
cocos2d-x-3.4
我也觉得没有用,但是我不确定引擎这样写的用意,所以没有去掉
你上锁, 一搬只在公用数据的 存/储 处理上锁和解锁
比如:
push 入列表时候:
lock
push 入列表
unlock
锁的东西尽量短小,事件和其他处理 只用在解锁后 调用
你上面的代码, 不用把log代码写在锁里面,可以在解锁后