BsTaskScheduler.h 4.1 KB

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