C++11 多线程问题

#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了,

:6: :6: :6: :6: :6:

:11: :11: :11:

你用的哪个版本的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代码写在锁里面,可以在解锁后