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;
} 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不是入队了么?直接将指针删除也不出队不会出问题吗 不会出错!
你注意看后面的代码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 编辑 ] 不要用ASSERT包裹正常执行的代码,极其容易造成奇怪的错误。因为ASSERT在Release模式下不编译!
ACE_ASSERT(this->followers_.dequeue_head (fw) ==0);
页:
[1]