2016年10月18日 星期二

1018 std::thread 使用(建立class 避免無法釋放資源)

修改成功的範例:
功能
1.建立為class 可以自己釋放資源
2.釋放的thread 記得用join 
3.利用 getInstance() ,使程式不用特定init
   (不過在此還是有特定建立無用的initCMDData() 來提早初始化
4.確認再PC上可以正常結束 不會有異常


.H
class PomeloThreadClass 
{
public:
//CREATE_FUNC(PomeloThreadClass);
PomeloThreadClass();
~PomeloThreadClass();
static PomeloThreadClass* getInstance();
//指令相關函數.
void saveCMD(int cmdID, const char* pData); //紀錄指令資料.
void nextCMDID(); //指向下一個空間.
bool bNewCmdID(); //判斷是否有新指令.
void initCMDData(); //初始化指令空間
//執行緒主函數
void initThread();
void notify();
void mainFunction();
private:
std::thread pomelo_thread;
std::mutex pomelo_mtx;
std::condition_variable pomelo_threadcv;
bool ThreadEndFlag ;
pomeloCmd_t pomeloCMD[MAX_POMELO_CMDID];
int pomelpCmdIdx_Save ;
int pomelpCmdIdx_Now ;
};

.CPP //非完整程式碼 部分函數沒有貼上


static PomeloThreadClass* m_Thread = nullptr;
PomeloThreadClass::PomeloThreadClass():
ThreadEndFlag(false),
pomelpCmdIdx_Save(0),
pomelpCmdIdx_Now(0)
{
initCMDData();
}
void PomeloThreadClass::initCMDData()
{
for (int i = 0; i < MAX_POMELO_CMDID; i++)
{
memset(pomeloCMD, 0, sizeof(pomeloCmd_t));
pomeloCMD[i].cmdID = POCMDID_NULL_CMDID;
}
pomelpCmdIdx_Save = 0;
pomelpCmdIdx_Now = 0;

}
PomeloThreadClass::~PomeloThreadClass()
{
if (pomelo_thread.joinable())
pomelo_thread.join();
if (!m_Thread)
{
free(m_Thread);
m_Thread = nullptr;
}
}
PomeloThreadClass* PomeloThreadClass::getInstance()
{
if (!m_Thread)
{
m_Thread = new PomeloThreadClass;
m_Thread->initThread();
}
return m_Thread;
}
//建立接收的網路的thread
void PomeloThreadClass::initThread()
{
pomelo_thread = std::thread(&PomeloThreadClass::mainFunction, this);
pomelo_thread.detach(); //產生新的Thread 不用等待結束
}
//通知thread
void PomeloThreadClass::notify()
{
pomelo_threadcv.notify_one(); //取得回傳數值
}
void PomeloThreadClass::mainFunction()
{
std::unique_lock<std::mutex> threadMtx(pomelo_mtx);
int restule = 0;
try
{
while (!ThreadEndFlag)
{
pomelo_threadcv.wait(threadMtx); //等待訊號
while (bNewCmdID())
{
switch (pomeloCMD[pomelpCmdIdx_Now].cmdID)
{
case POCMDID_Login:
log("LogOK");
ChangLayer_MainSlot();
break;
default:

break;
}
nextCMDID();
}
}
}
catch (std::exception const & ex) 
{
log("it's trouble when thread close");
// perhaps log the message, ex.what()
}



}



原始參考範例
https://stackoverflow.com/questions/38538438/how-to-terminate-a-stdthread
class YourClass {
public:
    ~YourClass() {
        if (_thread != nullptr) {
            _thread->join();
            delete _thread;
        }
    }
    void mainProcees() {
        _thread = new thread(&YourClass::downloadImg,this);
    }
private:
    thread *_thread = nullptr;
};
UPDATE
Just as @milleniumbug pointed out, you don't need dynamic allocation for the thread object, since it is movable. So the other solution is as follows.
class YourClass {
public:
    ~YourClass() {
        if (_thread.joinable())
            _thread.join();
    }
    void mainProcess() {
        _thread = std::thread(&YourClass::downloadImg, this);
    }
private:
    std::thread _thread;
};

cocos2dx-lua 建立滑鼠監聽

重要關鍵字  EVENT_MOUSE_SCROLL addEventListenerWithSceneGraphPriority      if IsPc() then --建立滑鼠監聽         local listener = cc.EventListenerMouse...