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();

}