ThreadHive.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <anki/util/Thread.h>
  7. #include <anki/util/DynamicArray.h>
  8. #include <anki/util/Allocator.h>
  9. namespace anki
  10. {
  11. // Forward
  12. class ThreadHive;
  13. /// @addtogroup util_thread
  14. /// @{
  15. /// Opaque handle that defines a ThreadHive depedency.
  16. /// @memberof ThreadHive
  17. using ThreadHiveDependencyHandle = U16;
  18. /// The callback that defines a ThreadHibe task.
  19. /// @memberof ThreadHive
  20. using ThreadHiveTaskCallback = void (*)(void*, U32 threadId, ThreadHive& hive);
  21. /// Task for the ThreadHive.
  22. /// @memberof ThreadHive
  23. class ThreadHiveTask
  24. {
  25. public:
  26. /// What this task will do.
  27. ThreadHiveTaskCallback m_callback ANKI_DBG_NULLIFY_PTR;
  28. /// Arguments to pass to the m_callback.
  29. void* m_argument ANKI_DBG_NULLIFY_PTR;
  30. /// The tasks that this task will depend on.
  31. WeakArray<ThreadHiveDependencyHandle> m_inDependencies;
  32. /// Will be filled after the submission of the task. Can be used to set
  33. /// dependencies to future tasks.
  34. ThreadHiveDependencyHandle m_outDependency;
  35. };
  36. /// A scheduler of small tasks. It takes a number of tasks and schedules them in
  37. /// one of the threads. The tasks can depend on previously submitted tasks or be
  38. /// completely independent.
  39. class ThreadHive : public NonCopyable
  40. {
  41. public:
  42. static const U MAX_THREADS = 32;
  43. /// Create the hive.
  44. ThreadHive(U threadCount, GenericMemoryPoolAllocator<U8> alloc);
  45. ~ThreadHive();
  46. U getThreadCount() const
  47. {
  48. return m_threadCount;
  49. }
  50. /// Submit tasks. The ThreadHiveTaskCallback callbacks can also call this.
  51. void submitTasks(ThreadHiveTask* tasks, U taskCount);
  52. /// Submit a single task without dependencies. The ThreadHiveTaskCallback
  53. /// callbacks can also call this.
  54. void submitTask(ThreadHiveTaskCallback callback, void* arg)
  55. {
  56. ThreadHiveTask task;
  57. task.m_callback = callback;
  58. task.m_argument = arg;
  59. submitTasks(&task, 1);
  60. }
  61. /// Wait for all tasks to finish. Will block.
  62. void waitAllTasks();
  63. private:
  64. static const U MAX_TASKS_PER_SESSION = 1024 * 2;
  65. class Thread;
  66. /// Lightweight task.
  67. class Task;
  68. GenericMemoryPoolAllocator<U8> m_alloc;
  69. Thread* m_threads = nullptr;
  70. U32 m_threadCount = 0;
  71. DynamicArray<Task> m_storage; ///< Task storage.
  72. DynamicArray<ThreadHiveDependencyHandle> m_deps; ///< Dependencies storage.
  73. Task* m_head = nullptr; ///< Head of the task list.
  74. Task* m_tail = nullptr; ///< Tail of the task list.
  75. Bool m_quit = false;
  76. U32 m_pendingTasks = 0;
  77. U32 m_allocatedTasks = 0;
  78. U32 m_allocatedDeps = 0;
  79. Mutex m_mtx;
  80. ConditionVariable m_cvar;
  81. void threadRun(U threadId);
  82. /// Wait for more tasks.
  83. Bool waitForWork(U threadId, Task*& task);
  84. /// Get new work from the queue.
  85. Task* getNewTask();
  86. /// Complete a task.
  87. void completeTask(U taskId);
  88. /// Inject dummy depedency tasks if there are
  89. };
  90. /// @}
  91. } // end namespace anki