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

字体:  

LF_ThreadPool的代码有点看不懂

peakzhang 发表于: 2008-5-11 17:19 来源: ACE 开发者

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;
}

最新回复

peakzhang at 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不是入队了么?直接将指针删除也不出队不会出问题吗
jiandan132 at 2008-5-29 18:05:43
不会出错!



你注意看后面的代码

CODE:

int
LF_ThreadPool::elect_new_leader (void)
{
  ACE_TRACE (ACE_TEXT ("LF_ThreadPool::elect_new_leader"));

  ACE_GUARD_RETURN
    (ACE_Thread_Mutex, leader_mon, this->leader_lock_, -1);
  leader_active(0);

  // Wake up a follower
  if (!followers_.is_empty ())
    {
      ACE_GUARD_RETURN (ACE_Thread_Mutex,
                        follower_mon,
                        this->followers_lock_,
                        -1);
      // Get the old follower.
      Follower *fw;
      ACE_ASSERT  (this->followers_.dequeue_head (fw) ==0);
      ACE_DEBUG ((LM_ERROR,
                  ACE_TEXT ("(%t) Resigning and Electing %d\n"),
                  fw->owner ()));
      ACE_ASSERT (fw->signal () == 0);
      return 0;
    }
  else
    {
      ACE_DEBUG
        ((LM_ERROR, ACE_TEXT ("(%t) Oops no followers left\n")));
      return -1;
    }
}
}
里面的

CODE:

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 编辑 ]
winston at 2008-5-29 22:26:51
不要用ASSERT包裹正常执行的代码,极其容易造成奇怪的错误。因为ASSERT在Release模式下不编译!
ACE_ASSERT  (this->followers_.dequeue_head (fw) ==0);