Task的设计与分析

Task是一个状态机,主要用于应用在单个线程里面执行多任务的情况。VZSIP中的Task是移植google libjingle里面的Task,并对它做了一些小的适应性修改。每一个Task都是一个小型的状态机,也就是说每一个Task都有自己的状态。这些状态之间的转移是通过推动TaskRunner来进行的。TaskRunner负责运行所有的Task,让Task从一个状态转移到另一个状态,直到Task结束为止。 状态机的类关系

上图是整个状态机的类关系,一共有三个类。

所有的Task都被TaskRunner管理着,一个Task继承者可以是另一个Task的子类,也可以是TaskRunner本身。实际上,TaskRunner就是上面所说的Top Task。所有的Task都是他的Child,我们在管理的时候也只需要管理这个TaskRunner就可以控制整个业务。要启动一个Task则需要调用这个Task的Start方法,一旦调用了这个方法,就在ProcessStart()里面处理自己的业务。而我们在定义自己的Task的时候,只需要注意在什么状态下Task应该做什么样的工作这样的框架下面,专注于自己的业务,让一切变得非常简单。

下面,将会对Task进行比较深入的分析。首先每一个Task内部都有固定的几个重要的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Executes a sequence of steps

class Task : public TaskParent {
 public:
  Task(TaskParent *parent);
  virtual ~Task();
  // Omitted some content, see the code task.h

  void Start();
  void Step();
  // Omitted some content, see the code task.h 

protected:
  virtual int OnTimeout() {
    // by default, we are finished after timing out

    return STATE_DONE;
  }
 protected:
  virtual std::string GetStateName(int state) const;
  virtual int Process(int state);
  virtual void Stop();
  virtual int ProcessStart() = 0;
  virtual int ProcessResponse() { return STATE_DONE; }
  // Omitted some content, see the code task.h

};
enum {
  STATE_BLOCKED = -1,
  STATE_INIT = 0,
  STATE_START = 1,
  STATE_DONE = 2,
  STATE_ERROR = 3,
  STATE_RESPONSE = 4,
  STATE_NEXT = 5,  // Subclasses which need more states start here and higher
};

如上面的枚举变量所示,所有的Task都内置了这七种状态。

Task的状态管理,看起来是比较麻烦,主要是文字描述上面有一些缺陷。

状态转移图

如上图所示,这就是整个Task执行过程中的状态转移图。绿色都是状态,而蓝色是其中关于Task里面被执行的过程。可以看到,一般情况下只会执行里面的ProcessStart

其它状态都不会再回调Task自身的函数了。

##VzsipTask的设计 在正常情况下,所有的Task的生命周期都归于TaskRunner来进行管理。那么TaskRunner的生命周期什么时候结束呢?在没有异步事件的情况下。TaskRunner执行完任务之后就会退出,可以认为这个时候TaskRunner的生命周期结束了。但是,如果有的任务出现BLOKED现象,显然一次RunTask是完全不够的。这个时候就需要连续