找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6080|回复: 3

Proactor使用中的问题

[复制链接]
发表于 2008-9-10 22:55:55 | 显示全部楼层 |阅读模式
我在使用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在删除它。
//异步反应器框架类
  1. class SEA_Proactor : public ACE_Task<ACE_MT_SYNCH>
  2. {
  3. public :
  4. SEA_Proactor():
  5.         sem_ ((unsigned int) 0),
  6.         proactor_(0){}
  7. virtual ~SEA_Proactor()
  8. {
  9.         (void) this->stop ();//停止异步方应器
  10.         this->delete_proactor();//删除已创建的异步反应器
  11. }
  12.     //启动异步反应器
  13. virtual int start(int iThreads)//启动线程的数目)
  14. {
  15.   //创建一个异步反应器
  16.   if(this->create_proactor() == -1)
  17.    return -1;
  18.         //启动异步方应器线程函数
  19.         if(this->activate (THR_JOINABLE | THR_NEW_LWP,iThreads) == -1)
  20.    return -1;
  21.         //线程池中的每个线程等待获取线程锁
  22.         for(;iThreads > 0;iThreads--)
  23.   {
  24.             if(sem_.acquire() == -1)
  25.     return -1;
  26.   }
  27.         return 0;
  28. }
  29.     //停止异步方应器
  30. virtual int stop(void)
  31. {
  32.   //停止异步反应器内核运行
  33.   if(this->proactor_ != 0)
  34.   {
  35.     ACE_Proactor::end_event_loop(); //执行到这一句就出错
  36.   }
  37.   //等待异步反应器线程函数结束
  38.   if(this->wait () == -1)
  39.       return -1;
  40.   return 0;
  41. }
  42.     //异步方应器线程函数
  43. virtual int svc(void)
  44. {
  45.   //发出解锁信号表示线程函数已经开始运行
  46.         sem_.release(1);
  47.         //开始异步反应器内核运行
  48.         ACE_Proactor::run_event_loop();
  49.   return 0;
  50. }
  51. private:
  52. //创建一个异步反应器
  53.     int create_proactor(void)
  54. {
  55.   //定义一个32位windows操作系统下的异步反应器接口类的指针
  56.         ACE_WIN32_Proactor *proactor_impl = 0;
  57.         //实例化这个指针
  58.         ACE_NEW_RETURN (proactor_impl,
  59.                         ACE_WIN32_Proactor,
  60.                         -1);
  61.         //实例化一个ACE的异步反应器类,并和前一个异步反应器接口类绑定
  62.         ACE_NEW_RETURN (this->proactor_,
  63.                         ACE_Proactor (proactor_impl, 1 ),
  64.                         -1);
  65.         //将异步反应器单体类的实例指向实例化的ACE异步反应器类
  66.         ACE_Proactor::instance (this->proactor_, 1);
  67.         return 0;
  68. }
  69.     //删除已创建的异步反应器
  70.     void delete_proactor(void)
  71. {
  72.   if(this->proactor_ != 0)
  73.   {
  74.       ACE_Proactor::close_singleton ();
  75.             this->proactor_ = 0;
  76.   }
  77. }
  78.     ACE_Thread_Semaphore sem_;//线程池信号
  79. ACE_Thread_Semaphore sem1_;//线程池信号
  80.     ACE_Proactor * proactor_;//异步反应器实例指针
  81. };
  82. //main函数测试
  83. int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
  84. {
  85. SEA_Proactor *test;
  86. ACE_NEW_RETURN(test, SEA_Proactor, -1);
  87. test->start(1);
  88. ACE_OS::sleep(1); //只要有这句话(换成scanf,或者弹出一个框,产生一个耽搁的时间)就要出错
  89. delete test;   
  90. return 0;
  91. }
复制代码
 楼主| 发表于 2008-9-10 22:56:08 | 显示全部楼层
代码里面错漏很多。
ACE_Task是不能直接删除的,需要让他停止队列的运作。
virtual int svc(void)
你的停止过程,是在析构函数里面,不推荐,因为析构函数里面运行,常常意味着其它附属资源的释放,比如你的类成员函数已经释放掉了。
(void) this->stop ();//停止异步方应器
this->delete_proactor();//删除已创建的异步反应器
这两句调用,缺乏同步关系,导致task被删除了,svc和Proactor还在跑,肯定报错。
 楼主| 发表于 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。
 楼主| 发表于 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()一下。
你的代码很危险,因为删除的对象和运行的线程之间没有同步关系,极其容易因为崩溃错误。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-4 15:45 , Processed in 0.029182 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表