BsTaskScheduler.h 4.3 KB

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