找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 5500|回复: 3

LF_ThreadPool的代码有点看不懂

[复制链接]
发表于 2008-5-11 17:19:44 | 显示全部楼层 |阅读模式
APG\ThreadPools中的LF_ThreadPool有点看不懂,
int
LF_ThreadPool::become_leader (void)
{
ACE_GUARD_RETURN
  (ACE_Thread_Mutex, leader_mon, this->leader_lock_, -1);
if (leader_active ())
{
  Follower *fw = make_follower ();//生成一个Follower并入队,可下面用delete不会出错吗?
  {
   // Wait until told to do so.
   while (leader_active ())
    fw->wait ();
  }
  delete fw;
}
leader_active (ACE_Thread::self ());
return 0;
}
 楼主| 发表于 2008-5-11 17:19:52 | 显示全部楼层
Follower*
LF_ThreadPool::make_follower (void)
{
ACE_TRACE (ACE_TEXT ("LF_ThreadPool::make_follower"));

ACE_GUARD_RETURN
  (ACE_Thread_Mutex, follower_mon, this->followers_lock_, 0);
Follower *fw;
ACE_NEW_RETURN (fw, Follower (this->leader_lock_), 0);
this->followers_.enqueue_tail (fw);
return fw;
}

fw不是入队了么?直接将指针删除也不出队不会出问题吗
发表于 2008-5-29 18:05:43 | 显示全部楼层
不会出错!



你注意看后面的代码
  1. int
  2. LF_ThreadPool::elect_new_leader (void)
  3. {
  4.   ACE_TRACE (ACE_TEXT ("LF_ThreadPool::elect_new_leader"));
  5.   ACE_GUARD_RETURN
  6.     (ACE_Thread_Mutex, leader_mon, this->leader_lock_, -1);
  7.   leader_active(0);
  8.   // Wake up a follower
  9.   if (!followers_.is_empty ())
  10.     {
  11.       ACE_GUARD_RETURN (ACE_Thread_Mutex,
  12.                         follower_mon,
  13.                         this->followers_lock_,
  14.                         -1);
  15.       // Get the old follower.
  16.       Follower *fw;
  17.       ACE_ASSERT  (this->followers_.dequeue_head (fw) ==0);
  18.       ACE_DEBUG ((LM_ERROR,
  19.                   ACE_TEXT ("(%t) Resigning and Electing %d\n"),
  20.                   fw->owner ()));
  21.       ACE_ASSERT (fw->signal () == 0);
  22.       return 0;
  23.     }
  24.   else
  25.     {
  26.       ACE_DEBUG
  27.         ((LM_ERROR, ACE_TEXT ("(%t) Oops no followers left\n")));
  28.       return -1;
  29.     }
  30. }
  31. }
复制代码
里面的
  1. ACE_ASSERT  (this->followers_.dequeue_head (fw) ==0);
复制代码
已经把这个 Follower 移出队列了,这是在另一个线程里做的,所以不容易理解。

这也是 APG 里说的:“Leader/Follower 模式的代码比较难写”的一个体现吧。



关键就是要知道:有一个共享的 Follower 队列,所有线程都可以操作这个队列!



或者再解释一下APG里 Leader/Follower 的例子代码的执行流程:



1、LF_ThreadPool 初始化了 n 个线程

2、n 个线程分别创建了各自的 Follower 对象并加入到一个全局的 Follower 队列

3、利用 leader_lock_ 这个 Mutex 的互斥能力,随机会有一个 Follower 进入临界区而成为 Leader

4、所有 Follower 都会在自己的 Follower 对象里的条件变量上等待,直到有 Leader 通知自己可以继续执行

5、这个 Leader 在执行任务前调用 elect_new_leader 来选举一个 Leader,选举的方法是从全局的 Follower 队列上摘一个 Follower,用 Signal 激活这个在条件变量上等待的线程

6、一旦这个线程被 Signal 激活,他恢复执行时会执行到 delete fw,而此时这个 Follower 已经从队列中被摘除了(在第5步,被 Leader 线程摘除的),因此就必须 delete fw了

[ 本帖最后由 jiandan132 于 2008-5-29 18:07 编辑 ]
发表于 2008-5-29 22:26:51 | 显示全部楼层
不要用ASSERT包裹正常执行的代码,极其容易造成奇怪的错误。因为ASSERT在Release模式下不编译!
ACE_ASSERT  (this->followers_.dequeue_head (fw) ==0);
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-5-9 15:25 , Processed in 0.014221 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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