BsTaskScheduler.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #pragma once
  2. #include "BsPrerequisitesUtil.h"
  3. #include "BsModule.h"
  4. #include "BsThreadPool.h"
  5. namespace BansheeEngine
  6. {
  7. /**
  8. * @brief Task priority. Tasks with higher priority will get executed sooner.
  9. */
  10. enum class TaskPriority
  11. {
  12. VeryLow = 98,
  13. Low = 99,
  14. Normal = 100,
  15. High = 101,
  16. VeryHigh = 102
  17. };
  18. /**
  19. * @brief Represents a single task that may be queued in the TaskScheduler.
  20. *
  21. * @note Thread safe.
  22. */
  23. class BS_UTILITY_EXPORT Task
  24. {
  25. struct PrivatelyConstruct {};
  26. public:
  27. Task(const PrivatelyConstruct& dummy, const String& name, std::function<void()> taskWorker,
  28. TaskPriority priority, TaskPtr dependency);
  29. /**
  30. * @brief Creates a new task. Task should be provided to TaskScheduler in order for it
  31. * to start.
  32. *
  33. * @param name Name you can use to more easily identify the task.
  34. * @param taskWorker Worker method that does all of the work in the task.
  35. * @param priority (optional) Higher priority means the tasks will be executed sooner.
  36. * @param dependency (optional) Task dependency if one exists. If provided the task will
  37. * not be executed until its dependency is complete.
  38. */
  39. static TaskPtr create(const String& name, std::function<void()> taskWorker, TaskPriority priority = TaskPriority::Normal,
  40. TaskPtr dependency = nullptr);
  41. /**
  42. * @brief Returns true if the task has completed.
  43. */
  44. bool isComplete() const;
  45. /**
  46. * @brief Returns true if the task has been canceled.
  47. */
  48. bool isCanceled() const;
  49. /**
  50. * @brief Blocks the current thread until the task has completed.
  51. *
  52. * @note While waiting adds a new worker thread, so that the blocking threads core can be utilized.
  53. */
  54. void wait();
  55. /**
  56. * @brief Cancels the task and removes it from the TaskSchedulers queue.
  57. */
  58. void cancel();
  59. private:
  60. friend class TaskScheduler;
  61. String mName;
  62. TaskPriority mPriority;
  63. UINT32 mTaskId;
  64. std::function<void()> mTaskWorker;
  65. TaskPtr mTaskDependency;
  66. std::atomic<UINT32> mState; /**< 0 - Inactive, 1 - In progress, 2 - Completed, 3 - Canceled */
  67. TaskScheduler* mParent;
  68. };
  69. /**
  70. * @brief Represents a task scheduler running on multiple threads. You may queue
  71. * tasks on it from any thread and they will be executed in user specified order
  72. * on any available thread.
  73. *
  74. * @note Thread safe.
  75. *
  76. * This type of task scheduler uses a global queue and is best used for coarse granularity of tasks.
  77. * (Number of tasks in the order of hundreds. Higher number of tasks might require different queuing and
  78. * locking mechanism, potentially at the cost of flexibility.)
  79. *
  80. * By default the task scheduler will create as many threads as there are physical CPU cores. You may add or remove
  81. * threads using addWorker/removeWorker methods.
  82. */
  83. class BS_UTILITY_EXPORT TaskScheduler : public Module<TaskScheduler>
  84. {
  85. public:
  86. TaskScheduler();
  87. ~TaskScheduler();
  88. /**
  89. * @brief Queues a new task.
  90. */
  91. void addTask(const TaskPtr& task);
  92. /**
  93. * @brief Adds a new worker thread which will be used for executing queued tasks.
  94. */
  95. void addWorker();
  96. /**
  97. * @brief Removes a worker thread (as soon as its current task is finished).
  98. */
  99. void removeWorker();
  100. protected:
  101. friend class Task;
  102. /**
  103. * @brief Main task scheduler method that dispatches tasks to other threads.
  104. */
  105. void runMain();
  106. /**
  107. * @brief Worker method that runs a single task.
  108. */
  109. void runTask(TaskPtr task);
  110. /**
  111. * @brief Blocks the calling thread until the specified task has completed.
  112. */
  113. void waitUntilComplete(const Task* task);
  114. /**
  115. * @brief Method used for sorting tasks.
  116. */
  117. static bool taskCompare(const TaskPtr& lhs, const TaskPtr& rhs);
  118. HThread mTaskSchedulerThread;
  119. Set<TaskPtr, std::function<bool(const TaskPtr&, const TaskPtr&)>> mTaskQueue;
  120. Vector<TaskPtr> mActiveTasks;
  121. UINT32 mNumActiveTasks;
  122. UINT32 mMaxActiveTasks;
  123. UINT32 mNextTaskId;
  124. bool mShutdown;
  125. BS_MUTEX(mReadyMutex);
  126. BS_MUTEX(mCompleteMutex);
  127. BS_MUTEX(mActiveTaskMutex);
  128. BS_THREAD_SYNCHRONISER(mTaskReadyCond);
  129. BS_THREAD_SYNCHRONISER(mTaskCompleteCond);
  130. };
  131. }