GNUGK(2.2.3)源代码分析之线程池结构

GNUGK2.2.3一改之前2.0版本版本的单线程结构。采用了作业(Job,Task)-代理(Agent)-执行者(Worker)三层控制结构 。使整个体系结构更加易于扩展和清晰。

在这里主要分析Job,Task,Agent,Worker他们之间的关系,以及Job的派生类Jobs与RegularJob时等。

理解Job,Agent,Worker三个类之间的关系,需要跟大家复习一下操作系统中的程序,进程,和CPU调度程序。

程序,是一个程序代码,数据等的集合。

进程,是一个正在运行的抢占CPU资源的程序。是程序的一个实例。

CPU调度程序,决定了当前那个进程可以运行,可以获得CPU的控制权限。

在这里的Job和操作系统中的程序是类似的,我们只要在Job的派生类中的Run函数编写我们要执行的程序代码即可。然后创建该Job的一个实例,并把该Job提交给Agent,Agent就会为该Job非配一个Worker来执行Job中的Run代码。因此他们之间和操作系统的程序,进程,CPU调度程序的对应关系是:

Job-----------程序

Agent------CPU调度进程

Worker----正在运行的进程

/job.h//

// // // job.h // // Abstraction of threads' jobs // //

#ifndef JOB_H #define JOB_H "@(#) $Id: job.h,v 1.6 2005/04/24 16:39:44 zvision Exp $"

#include "name.h"

/** The base abstract class that represents job objects.     This class implements the way to execute the job.     Derived classes implement actual jobs (override Run()).  Jobs are executed and managed by internal Job managment system  consisting of the singleton Agent object and Worker threads  that accept and execute new Jobs.    Specialized Job examples are:     Jobs - executes series of Tasks     RegularJob - executes a Task again and again until stopped     SimpleJob - calls some funtion with one pointer-type argument     SimpleJobA - calls some funtion with two arguments : pointer-type and reference     SimpleClassJob - calls a member function of some class that takes no arguments     SimpleClassJobA - calls a member function of some class that takes one                    argument of reference type */

// Job,代表一个具体要执行的任务 class Job : public NamedObject { public:  virtual ~Job();

 /// Perform the actual job, return when it is done  /* Job 真正要执行的代码,只要在派生类实现该函数即可*/  virtual void Run() = 0;

 /// Stop a running job  virtual void Stop();

 /** Execute the job in a first idle Worker thread.   The function returns immediatelly and this object   is delete automatically, when the job is finished.   使用该函数,把此job提交到Agent,由agent分配执行者  */  void Execute();

 /// Stop all jobs being currently executed by Worker threads  static void StopAll(); };

/** Similar to the Job, but is even more abstract. It does not contain  any Task management routines. Main purpose of this class it to provide  a way to represent a serie of Tasks that are to be executed one after another.

Task是一个比Job更小的执行任务,如果把Job当作操作系统的批处理任务,那么Task只是其中的一个小任务 */

class Task { public:  Task() : m_next(NULL), m_done(false) {}  virtual ~Task();

 /// Perform the actual task and return when it is finished

//Task具体要执行的代码,在其派生类的函数中要实现Exec这个函数。在调用Job->Run的时候会调用该函数  virtual void Exec() = 0;

 /** @return      true if the task is done and a next task is being processed.  */  bool IsDone() const { return m_done; }    /// Setup a task to be executed when this one is done

//Task是一个单向链表结构,设置下一个Task  void SetNext(   /// next task to be executed   Task* next   )  {   if (m_next != NULL && m_next != this)    m_next->SetNext(next);   else    m_next = next;  }

 /** @return      true if this is not the last task.

是否还有可执行的Task  */  bool HasNext() const { return m_next != NULL; }

 /** Get a next task and mark this one as done.      @return      The task that is next or NULL if this is the last task.

 执行完成一个Task以后,设置下一个要执行的Task,并标识该Task已经执行完成,

done=true  */  Task* DoNext()  {   Task* next = m_next;   if (next != this) // do not set m_done flag for circular task    m_done = true;   return next;  }

private:  /// next task to be executed when this one is done  Task* m_next;  /// true if the task is finished  bool m_done; };

/// Execute a task or a serie of tasks

// 重复不断执行的Job,不是循环的执行某一段共同的代码 class Jobs : public Job { public:  Jobs(   /// task to be executed   Task* task   ) : m_current(task) {}

 /// process the associated task (override from Job)  virtual void Run();

private:  /// task (or a serie of tasks) to be executed  Task* m_current; };

/** Regular job - executes the same task until it is stopped  (by calling Stop()). The actual work is to be done in the virtual  Exec() method in derived classes. RegularJob is an abstract class.

顺序的执行多个Job,Job与Job之间可以没有任何关系 */ class RegularJob : public Job { public:  RegularJob();

 /** @return   true if the job has not been yet stopped  */  bool IsRunning() const { return !m_stop; }

 /// override from Job  virtual void Run();

 /// repeated activity to be executed by this RegularJob

//真正要执行的代码,在派生类中继承该函数,就是重复Job要执行的具体代码  virtual void Exec() = 0;     /** Stop this job. NOTE: Acquire m_deletionPreventer mutex first      to make sure this object is not deleted before the method that   called Stop returns (if Stop is called from a derived class).  */  virtual void Stop();

protected:  // new virtual function

 /// Callback function that is called before the job is started.  virtual void OnStart();

 /** Callback function that is called when the job is stopped.   NOTE: This function is called with m_deletionPreventer mutex acquired.  */  virtual void OnStop();

 /// Wait for a signal (Signal())  void Wait() { m_sync.Wait(); }    /** Wait for a signal (Signal()).         @return      true if the sync point has been signalled.  */  bool Wait(   /// time to wait for the sync point to be signalled   const PTimeInterval& timeout   )  {   return m_sync.Wait(timeout) ? true : false;  }

 /// Send a signal to the waiting task  void Signal() { m_sync.Signal(); }

protected:  /// can be used when calling Stop to prevent the job to be deleted  /// (and invalid object being referenced) before the function  /// that called Stop returns  PMutex m_deletionPreventer;   private:  /// used by Wait and Signal member functions  PSyncPoint m_sync;  /// true if the job should be stopped  bool m_stop; };

用于创建Job的模板,把某个函数或者某个类的成员函数当作一个线程执行

也就是为函数f,分配一个线程来执行其代码

template<class F, class T> class SimpleJob : public Job { public:  SimpleJob(const F & _f, T *_t) : f(_f), t(_t) {}  virtual void Run() { f(t); }

private:  const F f;  T *t; };

template<class F, class T, class A> class SimpleJobA : public Job { public:  SimpleJobA(const F & _f, T *_t, const A & _a) : f(_f), t(_t), a(_a) {}  virtual void Run() { f(t, a); }

private:  const F f;  T *t;  A a; };

template<class T> class SimpleClassJob : public Job { public:  SimpleClassJob(T *_t, void (T::*_j)()) : t(_t), j(_j) {}  virtual void Run() { (t->*j)(); }

private:  T *t;  void (T::*j)(); };

template<class T, class A> class SimpleClassJobA : public Job { public:  typedef void (T::*CJob)(A);  SimpleClassJobA(T *_t, CJob _j, A _a) : t(_t), j(_j), a(_a) {}  virtual void Run() { (t->*j)(a); }

private:  T *t;  CJob j;  A a; };

template<class T> void CreateJob(T *t, void (T::*j)(), const char *n) {  Job *newjob = new SimpleClassJob<T>(t, j);  newjob->SetName(n);  newjob->Execute(); }

template<class T, class A> void CreateJob(T *t, void (T::*j)(A), A a, const char *n) {  Job *newjob = new SimpleClassJobA<T, A>(t, j, a);  newjob->SetName(n);  newjob->Execute(); }

#endif // JOB_H job.cxx//

// // // job.cxx // // #include <list> #include <ptlib.h> #include "stl_supp.h" #include "rwlock.h" #include "singleton.h" #include "job.h" #include "h323util.h"

// timeout (seconds) for an idle Worker to be deleted #define DEFAULT_WORKER_IDLE_TIMEOUT (10*60)

/** This class represents a thread that performs jobs. It has two states:     idle and busy. When it accepts a new Job, it becomes busy. When the job     is finished it becomes idle. Each idle Worker is stopped (deleted) after     the specified timeout, so Workers that are not needed anymore do not use     system resources. This makes passible to create dynamic sets of Workers. */ class Agent; class Worker : public PThread { public:  PCLASSINFO(Worker, PThread)

 /// create a new Worker thread and start it immediatelly  Worker(   /// pointer to the Agent instance that the worker is run under control of   Agent* agent,   /// timeout (seconds) for this Worker to be deleted, if idle   long idleTimeout = DEFAULT_WORKER_IDLE_TIMEOUT   );    ~Worker();

 /** Tell this Worker to execute a new Job. The function returns   immediatelly and the job is executed under control of the Worker thread.   After the job is finished, its object is deleted.      @return   true if this Worker is idle and has taken the Job, false otherwise   (on failuer the job object is not deleted).   提交job到worker线程,该job是worker下一个要执行的任务  */  bool Exec(   /// Job to be executed   Job* job   );     /** Stop the Worker thread and any jobs being executed,      wait for Worker thread termination and delete this object.      销毁Worker对象,不能使用delete,需要自我delete  */  void Destroy();

 PThreadIdentifer GetWorkerId(){ return m_id;};

private:  // override from class PThread  virtual void Main();

 /// idle timeout (seconds), after which the Worker is destoyed  PTimeInterval m_idleTimeout;  /// signals that either a new Job is present or the Worker is destroyed  PSyncPoint m_wakeupSync;  /// true if the Worker is being destroyed  bool m_closed;  /// for atomic job insertion and deletion  PMutex m_jobMutex;  /// actual Job being executed, NULL if the Worker is idle  Job* m_job;  /// Worker thread identifier  PThreadIdentifer m_id;  /// Agent singleton pointer to avoid unnecessary Instance() calls  Agent* m_agent; };

/** Agent singleton manages a set of Worker threads. It creates     new Workers if required. Idle Workers are deleted automatically  after configured idle timeout. */ class Agent : public Singleton<Agent> { public:  Agent();  ~Agent();

 /** Execute the job by the first idle Worker or a new Worker.   Delete the Job object after it is done.  */  void Exec(   /// the job to be executed   Job* job   );     /** Remove the Worker from busy and idle lists.   Called by the Worker when it deletes itself.  */  void Remove(   /// the worker to be removed from the lists   Worker* worker   );

 /** Move the Worker from the busy list to the idle list.   Called by the Worker when it finishes each job.  */  void JobDone(   /// the worker to be marked as idle   Worker* worker   );    private:  /// mutual access to Worker lists  PMutex m_wlistMutex;  /// list of idle Worker threads  std::list<Worker*> m_idleWorkers;  /// list of Worker threads executing some Jobs  std::list<Worker*> m_busyWorkers;  /// flag preventing new workers to be registered during Agent destruction  bool m_active; };

Worker::Worker(  /// pointer to the Agent instance that the worker is run under control of  Agent* agent,  /// timeout (seconds) for this Worker to be deleted, if idle  long idleTimeout  )  : PThread(5000, AutoDeleteThread),  m_idleTimeout(idleTimeout*1000), m_closed(false), m_job(NULL), m_id(0),  m_agent(agent) {  // resume suspended thread (and run Main)  Resume(); }

Worker::~Worker() {  PWaitAndSignal lock(m_jobMutex);  if (m_job) {   DEBUG_TEST(1, "JOB/tDestroying Worker " << m_id << " with active Job " << m_job->GetName());   delete m_job;   m_job = NULL;  }  DEBUG_TEST(5, "JOB/tWorker " << m_id << " destroyed"); }

void Worker::Main() {  m_id = GetThreadId();  DEBUG_TEST(5, "JOB/tWorker " << m_id << " started ");  

只要该worker没有停止,就会检测时候有Job提交到该Worker,如果有就执行之,

否则就睡觉去,等待Job的到来  while (!m_closed) {   bool timedout = false;   // wait for a new job or idle timeout expiration   if (m_job == NULL) {    timedout = !m_wakeupSync.Wait(m_idleTimeout);    if (timedout)    { DEBUG_TEST(5, "JOB/tIdle timeout for Worker " << m_id);    }   }   // terminate this worker if closed explicitly or idle timeout expired   if (m_closed || (timedout && m_job == NULL)) {

程序处于空闲的状态,好久没有任务可以执行,先停止,回去休息一下,等忙的时候再由Agent调出来

执行Job    m_closed = true;    break;   }      if (m_job) {    DEBUG_TEST(5, "JOB/tStarting Job " << m_job->GetName()     << " at Worker thread " << m_id     );

重点在这里,调用Job的Run函数,执行某个Job具体的指令,以完成其提交的任务。

   m_job->Run();

   {     PWaitAndSignal lock(m_jobMutex);     delete m_job;     m_job = NULL;    }        m_agent->JobDone(this);   }  }

 DEBUG_TEST(5, "JOB/tWorker " << m_id << " closed");    // remove this Worker from the list of workers  m_agent->Remove(this);  if (m_job)  {   DEBUG_TEST(1, "JOB/tActive Job " << m_job->GetName()    << " left at closing Worker thread " << m_id    );  } }

bool Worker::Exec(  /// Job to be executed  Job* job  ) {  // fast check if there is no job being executed  if( GetThreadId()== 0  )  {   DEBUG_TEST(0,"thread id is zeor "<<GetThreadId());   return false ;  }  if (m_job == 0 && !m_closed) {   PWaitAndSignal lock(m_jobMutex);   // check again there is no job being executed   if (m_job == 0 && !m_closed) {    m_job = job;    m_wakeupSync.Signal();    return true;   }  }  return false; }

void Worker::Destroy() {  // do not delete itself when the thread is stopped  SetNoAutoDelete();    m_jobMutex.Wait();  if (m_job)   m_job->Stop();  m_jobMutex.Signal();

 m_closed = true;  m_wakeupSync.Signal();    DEBUG_TEST(5, "JOB/tWaiting for Worker thread " << m_id << " termination");  WaitForTermination();  /* 自我销毁*/  delete this; }

Agent::Agent() : Singleton<Agent>("Agent"), m_active(true) { }

Agent::~Agent() {  DEBUG_TEST(5, "JOB/tDestroying active Workers for the Agent");

 std::list<Worker*> workers; #if PTRACING  int numIdleWorkers = -1;  int numBusyWorkers = -1; #endif    {   // move all workers to the local list   PWaitAndSignal lock(m_wlistMutex);   m_active = false; #if PTRACING   numIdleWorkers = m_idleWorkers.size();   numBusyWorkers = m_busyWorkers.size(); #endif   while (!m_busyWorkers.empty()) {    workers.push_front(m_busyWorkers.front());    m_busyWorkers.pop_front();   }   while (!m_idleWorkers.empty()) {    workers.push_front(m_idleWorkers.front());    m_idleWorkers.pop_front();   }  }

#if TEST_  DEBUG_TEST(5, "JOB/tWorker threads to cleanup: " << (numBusyWorkers+numIdleWorkers)   << " total - " << numBusyWorkers << " busy, " << numIdleWorkers << " idle"   ); #endif

 // destroy all workers  ForEachInContainer(workers, mem_vfun(&Worker::Destroy));    DEBUG_TEST(5, "JOB/tAgent and its Workers destroyed"); }

void Agent::Exec(  /// the job to be executed  Job* job  ) {  Worker* worker = NULL; #if PTRACING  int numIdleWorkers = -1;  int numBusyWorkers = -1; #endif  // pop the first idle worker and move it to the busy list   if (job) {   PWaitAndSignal lock(m_wlistMutex);   // delete the job if the Agent is being destroyed   if (!m_active) {    DEBUG_TEST(5, "JOB/tAgent did not accept Job " << job->GetName());    delete job;    job = NULL;    return;   }   /*如果有空闲的worker,从中其一个来执行worker*/   if (!m_idleWorkers.empty()) {    worker = m_idleWorkers.front();    m_idleWorkers.pop_front();    m_busyWorkers.push_front(worker); #if PTRACING    numIdleWorkers = m_idleWorkers.size();    numBusyWorkers = m_busyWorkers.size(); #endif   }  } else   return;    bool destroyWorker = false;     // if no idle worker has been found, create a new one  // and put it on the list of busy workers  /* 如果没有空闲的worker创建一个新的worker来执行job  并把worker加入忙队列*/  if (worker == NULL) {   worker = new Worker(this);

  PWaitAndSignal lock(m_wlistMutex);   if (m_active)    m_busyWorkers.push_front(worker);   else    destroyWorker = true; #if PTRACING   numIdleWorkers = m_idleWorkers.size();   numBusyWorkers = m_busyWorkers.size(); #endif  }    // execute the job by the worker  // if worker is running the the worker id > 0 else == 0  /*提交job到worker 如果提交失败,一般是worker  线程已经停止,  就删除job,否则不能删除job*/  if (!(m_active && worker->Exec(job))) {   // should not ever happen, but...   DEBUG_TEST(1,"can't execute the job,delete it "<<job->GetName());   delete job;   job = NULL;   PWaitAndSignal lock(m_wlistMutex);   m_busyWorkers.remove(worker);   if (m_active)    m_idleWorkers.push_front(worker);   else    destroyWorker = true; #if PTRACING   numIdleWorkers = m_idleWorkers.size();   numBusyWorkers = m_busyWorkers.size(); #endif  }

#if PTRACING  PTRACE_IF(5, m_active, "JOB/tWorker threads: " << (numBusyWorkers+numIdleWorkers)   << " total - " << numBusyWorkers << " busy, " << numIdleWorkers << " idle"   ); #endif

 if (destroyWorker) {   DEBUG_TEST(5, "JOB/tAgent did not accept Job " << job->GetName());   worker->Destroy();  } }

void Agent::Remove(  Worker* worker  ) { #if PTRACING  int numIdleWorkers;  int numBusyWorkers;  { #endif   PWaitAndSignal lock(m_wlistMutex);   // check both lists for the worker   m_idleWorkers.remove(worker);   m_busyWorkers.remove(worker); #if PTRACING   numIdleWorkers = m_idleWorkers.size();   numBusyWorkers = m_busyWorkers.size();  }  PTRACE_IF(5, m_active, "JOB/tWorker threads: " << (numBusyWorkers+numIdleWorkers)   << " total - " << numBusyWorkers << " busy, " << numIdleWorkers << " idle"   ); #endif }

void Agent::JobDone(  /// the worker to be marked as idle  Worker* worker  ) { #if PTRACING  int numIdleWorkers;  int numBusyWorkers;  { #endif   PWaitAndSignal lock(m_wlistMutex);   m_busyWorkers.remove(worker);   if (m_active)    m_idleWorkers.push_front(worker); #if PTRACING   numIdleWorkers = m_idleWorkers.size();   numBusyWorkers = m_busyWorkers.size();  }  PTRACE_IF(5, m_active, "JOB/tWorker threads: " << (numBusyWorkers+numIdleWorkers)   << " total - " << numBusyWorkers << " busy, " << numIdleWorkers << " idle"   ); #endif }

Task::~Task() { }

Job::~Job() {  DEBUG_TEST(5, "JOB/tJob " << GetName() << " deleted"); }

void Job::Execute() {

提交任务到代理,由代理调度执行  Agent::Instance()->Exec(this); }

void Job::Stop() { }

void Job::StopAll() {

停止整个程序的所有Job  delete Agent::Instance(); }

void Jobs::Run() {

执行Jobs  while (m_current) {   m_current->Exec();   m_current = m_current->DoNext();  } }

RegularJob::RegularJob() : m_stop(false) { }

void RegularJob::OnStart() { }

void RegularJob::OnStop() { }

void RegularJob::Run() {  OnStart();    while (!m_stop)   Exec();     // lock to allow a member function that is calling Stop  // return before OnStop is called and the object is deleted  PWaitAndSignal lock(m_deletionPreventer);  OnStop(); }

void RegularJob::Stop() {  // signal stop flag and wake up job thread, if it is in the waiting state  m_stop = true;  m_sync.Signal(); }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值