贝贝花花包包店,精品555皮具,钱夹,皮夹

字体:  

Proactor使用中的问题

peakzhang 发表于: 2008-9-10 22:55 来源: ACE 开发者

我在使用ACE5.5的时候,用到了其中的Proactor。
我的测试程序先创建了win32下的proactor后,在线程中启动了run_event_loop方法,然后在析构的时候调用了end_event_loop方法,可是每次在我调用end_event_loop方法的时候就要抛出一个异常,内容为:
"Unhandled exception in proact.exe(KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception"。
大家在使用ACE5.5的Proactor时有没有遇到过类似的问题呢?

下面是我的代码,只是简单的创建Proactor在删除它。
//异步反应器框架类

CODE:


class SEA_Proactor : public ACE_Task<ACE_MT_SYNCH>
{
public :
SEA_Proactor():
        sem_ ((unsigned int) 0),
        proactor_(0){}
virtual ~SEA_Proactor()
{
        (void) this->stop ();//停止异步方应器
        this->delete_proactor();//删除已创建的异步反应器
}
    //启动异步反应器
virtual int start(int iThreads)//启动线程的数目)
{
  //创建一个异步反应器
  if(this->create_proactor() == -1)
   return -1;
        //启动异步方应器线程函数
        if(this->activate (THR_JOINABLE | THR_NEW_LWP,iThreads) == -1)
   return -1;
        //线程池中的每个线程等待获取线程锁
        for(;iThreads > 0;iThreads--)
  {
            if(sem_.acquire() == -1)
    return -1;
  }
        return 0;
}
    //停止异步方应器
virtual int stop(void)
{
  //停止异步反应器内核运行
  if(this->proactor_ != 0)
  {
    ACE_Proactor::end_event_loop(); //执行到这一句就出错
  }
  //等待异步反应器线程函数结束
  if(this->wait () == -1)
      return -1;
  return 0;
}
    //异步方应器线程函数
virtual int svc(void)
{
  //发出解锁信号表示线程函数已经开始运行
        sem_.release(1);
        //开始异步反应器内核运行
        ACE_Proactor::run_event_loop();
  return 0;
}
private:
//创建一个异步反应器
    int create_proactor(void)
{
  //定义一个32位windows操作系统下的异步反应器接口类的指针
        ACE_WIN32_Proactor *proactor_impl = 0;
        //实例化这个指针
        ACE_NEW_RETURN (proactor_impl,
                        ACE_WIN32_Proactor,
                        -1);
        //实例化一个ACE的异步反应器类,并和前一个异步反应器接口类绑定
        ACE_NEW_RETURN (this->proactor_,
                        ACE_Proactor (proactor_impl, 1 ),
                        -1);
        //将异步反应器单体类的实例指向实例化的ACE异步反应器类
        ACE_Proactor::instance (this->proactor_, 1);
        return 0;
}
    //删除已创建的异步反应器
    void delete_proactor(void)
{
  if(this->proactor_ != 0)
  {
      ACE_Proactor::close_singleton ();
            this->proactor_ = 0;
  }
}
    ACE_Thread_Semaphore sem_;//线程池信号
ACE_Thread_Semaphore sem1_;//线程池信号
    ACE_Proactor * proactor_;//异步反应器实例指针
};
//main函数测试
int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
SEA_Proactor *test;
ACE_NEW_RETURN(test, SEA_Proactor, -1);
test->start(1);
ACE_OS::sleep(1); //只要有这句话(换成scanf,或者弹出一个框,产生一个耽搁的时间)就要出错
delete test;   
return 0;
}

最新回复

peakzhang at 2008-9-10 22:56:08
代码里面错漏很多。
ACE_Task是不能直接删除的,需要让他停止队列的运作。
virtual int svc(void)
你的停止过程,是在析构函数里面,不推荐,因为析构函数里面运行,常常意味着其它附属资源的释放,比如你的类成员函数已经释放掉了。
(void) this->stop ();//停止异步方应器
this->delete_proactor();//删除已创建的异步反应器
这两句调用,缺乏同步关系,导致task被删除了,svc和Proactor还在跑,肯定报错。
peakzhang at 2008-9-10 22:56:17
看了版主的回答,我还有以下几个问题:

1。"ACE_Task是不能直接删除的,需要让它停止队列的运作",我继承自ACE_Task是为了能让Proactor在线程里运行event_loop(),虽然ACE_Task里自带了一个msg_queue,但我并没有对它进行任何操作。斑竹的意思是让我加一句"this->msg_queue()->deactivate()"?

2。(void) this->stop ();//停止异步方应器
this->delete_proactor();//删除已创建的异步反应器
斑竹说上面这两句的调用缺乏同步关系,但我的问题是:每次调试只要到了end_event_loop()方法的时候就出错,我可以不把这些停止操作放在delete里面,可以在main函数里调用,但同样的,遇到end_event_loop时就要出错。我在end_event_loop调用之前需要做点什么其他的么?ACE提供给我们的就是一句end_event_loop。
peakzhang at 2008-9-10 22:56:25
//定义一个32位windows操作系统下的异步反应器接口类的指针
        ACE_WIN32_Proactor *proactor_impl = 0;
        //实例化这个指针
        ACE_NEW_RETURN (proactor_impl,
                        ACE_WIN32_Proactor,
                        -1);
        //实例化一个ACE的异步反应器类,并和前一个异步反应器接口类绑定
        ACE_NEW_RETURN (this->proactor_,
                        ACE_Proactor (proactor_impl, 1 ),
                        -1);
        //将异步反应器单体类的实例指向实例化的ACE异步反应器类
        ACE_Proactor::instance (this->proactor_, 1);
---------------------------------------------------------

上面代码全部可以不要,改成:
this->proactor_ = ACE_Proactor::instance();
因为Windows平台,默认的初始化对象就是ACE_WIN32_Proactor.
故障消除,出错的地方在:
int
ACE_WIN32_Asynch_Result::post_completion (ACE_Proactor_Impl *proactor)
{
  // Get to the platform specific implementation.
  ACE_WIN32_Proactor *win32_proactor = dynamic_cast<ACE_WIN32_Proactor *> (proactor);

  if (win32_proactor == 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       ACE_LIB_TEXT ("Dynamic cast to WIN32 Proactor failed\n")),
                      -1);

  // Post myself.
  return win32_proactor->post_completion (this);
}
你初始化的代码有问题,导致Proactor实际运行的,和你结束的不是一个对象,应该是这个问题。

ACE_Task的结束,需要等待svc结束,svc是另外的线程开启的,所以一般会wait()一下。
你的代码很危险,因为删除的对象和运行的线程之间没有同步关系,极其容易因为崩溃错误。