from: http://groups.csdn.net/boost_asio

通常我們使用線程的時候會有這樣的操作

在a線程空間中將事件交給b線程處理:

b.PostMessage();

這個操作是異步的,所以要傳給b線程的數據不能在棧上分配,而應該在堆上分配.

見下面的例子

void func()

{

    A a;

    b.PostMessage(nMsg, &a, 0);      

}

上面的例子因為a在棧上分配,當func()函數退出的時候,a的析構函數將被調用,a的占用的地址成為了一個無效的地址.

在以后的某個時候,當b線程式要處理這個消息的時候,用了一個無效的地址,這個時候異常就發生了.

所以通常這樣做:

void func()

{

    A *pa = new A();

    b.PostMessage(MSG_POST, pa, 0); 

這樣做解決了上面的問題,因為pa是在堆上new出來的,所以直到你調用 delete, pa才會析構.

但是如果只是這樣的話,那么會出現內存泄漏.因此要在處理消息后, 調用delete.

void ProcessMessage(unsignd nMsg, WPARAM wParam, LPARAM lParam)

{

    if (nMsg == MSG_POST)

    {

        A *pa = (A*)wParam;

        do_something (pa);

        delete pa;

    } 

 這樣做解決了內存泄漏的問題 .但是要人為地去管理pa的生命周期,而且容易忘記調用nMsg而產生內存泄漏.

所以也不是很好的做法.

 

我們有沒有一種辦法讓我們不用去管理這個pa的生命周期呢?

我們通過使用boost的異質容器類any和管理指針生命周期的shared_ptr來實現這一點.

 

struct CCommand
{
    typedef bst::shared_ptr<CCommand> CCmdPtr;
    unsigned int nCmd;
    bst::any anyParam;
};

這是一個消息對象,  nCmd是消息類型, anyParam存儲要傳遞的數據.它可以接受任何類型的數據.

我們實現一個ThreadEx類:

class CThreadEx
{
public:

    typedef boost::singal<void(const CCommand&)> CommandProcessor;

    CommandProcessor m_cmdProc;

    CThreadEx();
    ~CThreadEx();

    template<typename T>
        void PostCommand(unsigned nCmd, const bst::shared_ptr<T>& p)
    {
        bst::mutex::scoped_lock lock(m_mutex);
        CCommand::CCmdPtr cmd(new CCommand);
        cmd->nCmd = nCmd;
        cmd->anyParam = p;
        m_lstCmd.push_back(cmd);
    }

    template<typename T>
    void SendCommand(unsigned nCmd, const bst::shared_ptr<T>& p);

protected:
    virtual void ProcessCommand(const CCommand& cmd)

private:
    void ThreadRoutine()
    {
        while(1)
            CommandLoop();
    }
    void CommandLoop()
    {
        bst::mutex::scoped_lock lock(m_mutex);
        while (!m_lstCmd.empty())
        {
            CCommand::CCmdPtr cmd = m_lstCmd.front();
            m_lstCmd.pop_front();
            try
            {

                 if (!m_cmdProc.empty())

                       m_cmdProc(*cmd);
            }
            catch(boost::bad_any_cast& e)
            {//記錄出錯日志,退出線程
               
            }
        }
    }
private:
    std::list<CCommand::CCmdPtr> m_lstCmd;
    bst::mutex m_mutex;
};

 

  


 在PostCommand這個函數中,我們規定了第二個參數一定是一個shared_ptr類型的智能指針.之所以要這樣做,是希望

在編譯期提醒程序員一定要使用shared_ptr類型的對象作為參數.

 

我們像這樣使用:

 

class CMyThread

{

   CThreadEx m_thread;

 public:

     CMyThread()

    {

         m_thread.m_cmdProc.Connect(boost::bind(&CMyThread::ProcessCommand, this, _1));

    } 

    

     void ProcessCommand(const CCommand& cmd)

     {

          if (cmd.nCmd == 1)

          {

                bst::shared_ptr<int> n = boost::any_cast<bst::shared_ptr<int> >(cmd.anyParam);
                std::cout << *n <<std::endl;
 

          }

     }

 

     void AsyncProcess()

      {

             bst::shared_ptr<int> pInt(new int);
             *pInt = 8;

             m_thread.PostCommand(1, pInt);

      }

};

 

 

void main()

{

    CMyThread th;

    th.AsyncProcess();

    boost::thread::yield();

}