|
发表于 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 编辑 ] |
|