task.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright 2004 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef THIRD_PARTY_LIBJINGLE_XMPP_TASK_RUNNER_TASK_H_
  11. #define THIRD_PARTY_LIBJINGLE_XMPP_TASK_RUNNER_TASK_H_
  12. #include <stdint.h>
  13. #include <string>
  14. #include "third_party/libjingle_xmpp/task_runner/taskparent.h"
  15. /////////////////////////////////////////////////////////////////////
  16. //
  17. // TASK
  18. //
  19. /////////////////////////////////////////////////////////////////////
  20. //
  21. // Task is a state machine infrastructure. States are pushed forward by
  22. // pushing forwards a TaskRunner that holds on to all Tasks. The purpose
  23. // of Task is threefold:
  24. //
  25. // (1) It manages ongoing work on the UI thread. Multitasking without
  26. // threads, keeping it easy, keeping it real. :-) It does this by
  27. // organizing a set of states for each task. When you return from your
  28. // Process*() function, you return an integer for the next state. You do
  29. // not go onto the next state yourself. Every time you enter a state,
  30. // you check to see if you can do anything yet. If not, you return
  31. // STATE_BLOCKED. If you _could_ do anything, do not return
  32. // STATE_BLOCKED - even if you end up in the same state, return
  33. // STATE_mysamestate. When you are done, return STATE_DONE and then the
  34. // task will self-delete sometime afterwards.
  35. //
  36. // (2) It helps you avoid all those reentrancy problems when you chain
  37. // too many triggers on one thread. Basically if you want to tell a task
  38. // to process something for you, you feed your task some information and
  39. // then you Wake() it. Don't tell it to process it right away. If it
  40. // might be working on something as you send it information, you may want
  41. // to have a queue in the task.
  42. //
  43. // (3) Finally it helps manage parent tasks and children. If a parent
  44. // task gets aborted, all the children tasks are too. The nice thing
  45. // about this, for example, is if you have one parent task that
  46. // represents, say, and Xmpp connection, then you can spawn a whole bunch
  47. // of infinite lifetime child tasks and now worry about cleaning them up.
  48. // When the parent task goes to STATE_DONE, the task engine will make
  49. // sure all those children are aborted and get deleted.
  50. //
  51. // Notice that Task has a few built-in states, e.g.,
  52. //
  53. // STATE_INIT - the task isn't running yet
  54. // STATE_START - the task is in its first state
  55. // STATE_RESPONSE - the task is in its second state
  56. // STATE_DONE - the task is done
  57. //
  58. // STATE_ERROR - indicates an error - we should audit the error code in
  59. // light of any usage of it to see if it should be improved. When I
  60. // first put down the task stuff I didn't have a good sense of what was
  61. // needed for Abort and Error, and now the subclasses of Task will ground
  62. // the design in a stronger way.
  63. //
  64. // STATE_NEXT - the first undefined state number. (like WM_USER) - you
  65. // can start defining more task states there.
  66. //
  67. // When you define more task states, just override Process(int state) and
  68. // add your own switch statement. If you want to delegate to
  69. // Task::Process, you can effectively delegate to its switch statement.
  70. // No fancy method pointers or such - this is all just pretty low tech,
  71. // easy to debug, and fast.
  72. //
  73. // Also notice that Task has some primitive built-in timeout functionality.
  74. //
  75. // A timeout is defined as "the task stays in STATE_BLOCKED longer than
  76. // timeout_seconds_."
  77. //
  78. // Descendant classes can override this behavior by calling the
  79. // various protected methods to change the timeout behavior. For
  80. // instance, a descendand might call SuspendTimeout() when it knows
  81. // that it isn't waiting for anything that might timeout, but isn't
  82. // yet in the STATE_DONE state.
  83. //
  84. namespace jingle_xmpp {
  85. // Executes a sequence of steps
  86. class Task : public TaskParent {
  87. public:
  88. Task(TaskParent *parent);
  89. ~Task() override;
  90. int32_t unique_id() { return unique_id_; }
  91. void Start();
  92. void Step();
  93. int GetState() const { return state_; }
  94. bool HasError() const { return (GetState() == STATE_ERROR); }
  95. bool Blocked() const { return blocked_; }
  96. bool IsDone() const { return done_; }
  97. int64_t ElapsedTime();
  98. // Called from outside to stop task without any more callbacks
  99. void Abort(bool nowake = false);
  100. // Called inside the task to signal that the task may be unblocked
  101. void Wake();
  102. protected:
  103. enum {
  104. STATE_BLOCKED = -1,
  105. STATE_INIT = 0,
  106. STATE_START = 1,
  107. STATE_DONE = 2,
  108. STATE_ERROR = 3,
  109. STATE_RESPONSE = 4,
  110. STATE_NEXT = 5, // Subclasses which need more states start here and higher
  111. };
  112. // Called inside to advise that the task should wake and signal an error
  113. void Error();
  114. virtual std::string GetStateName(int state) const;
  115. virtual int Process(int state);
  116. virtual void Stop();
  117. virtual int ProcessStart() = 0;
  118. virtual int ProcessResponse();
  119. protected:
  120. private:
  121. void Done();
  122. int state_;
  123. bool blocked_;
  124. bool done_;
  125. bool aborted_;
  126. bool busy_;
  127. bool error_;
  128. int64_t start_time_;
  129. int64_t timeout_time_;
  130. int timeout_seconds_;
  131. bool timeout_suspended_;
  132. int32_t unique_id_;
  133. static int32_t unique_id_seed_;
  134. };
  135. } // namespace jingle_xmpp
  136. #endif // THIRD_PARTY_LIBJINGLE_XMPP_TASK_RUNNER_TASK_H_