peakzhang 发表于 2008-5-11 17:19:44

LF_ThreadPool的代码有点看不懂

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 发表于 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 发表于 2008-5-29 18:05:43

不会出错!



你注意看后面的代码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;
    }
}
}里面的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 发表于 2008-5-29 22:26:51

不要用ASSERT包裹正常执行的代码,极其容易造成奇怪的错误。因为ASSERT在Release模式下不编译!
ACE_ASSERT(this->followers_.dequeue_head (fw) ==0);
页: [1]
查看完整版本: LF_ThreadPool的代码有点看不懂