AsyncLoader.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <anki/resource/Common.h>
  7. #include <anki/util/Thread.h>
  8. namespace anki
  9. {
  10. /// @addtogroup resource
  11. /// @{
  12. /// Loader asynchronous task.
  13. class AsyncLoaderTask
  14. {
  15. friend class AsyncLoader;
  16. public:
  17. virtual ~AsyncLoaderTask()
  18. {
  19. }
  20. virtual ANKI_USE_RESULT Error operator()() = 0;
  21. private:
  22. AsyncLoaderTask* m_next = nullptr;
  23. };
  24. /// Asynchronous resource loader.
  25. class AsyncLoader
  26. {
  27. public:
  28. AsyncLoader();
  29. ~AsyncLoader();
  30. ANKI_USE_RESULT Error create(const HeapAllocator<U8>& alloc);
  31. /// Create a new asynchronous loading task.
  32. template<typename TTask, typename... TArgs>
  33. void newTask(TArgs&&... args);
  34. private:
  35. HeapAllocator<U8> m_alloc;
  36. Thread m_thread;
  37. Mutex m_mtx;
  38. ConditionVariable m_condVar;
  39. AsyncLoaderTask* m_head = nullptr;
  40. AsyncLoaderTask* m_tail = nullptr;
  41. Bool8 m_quit = false;
  42. /// Thread callback
  43. static ANKI_USE_RESULT Error threadCallback(Thread::Info& info);
  44. Error threadWorker();
  45. void stop();
  46. };
  47. //==============================================================================
  48. template<typename TTask, typename... TArgs>
  49. void AsyncLoader::newTask(TArgs&&... args)
  50. {
  51. TTask* newTask =
  52. m_alloc.template newInstance<TTask>(std::forward<TArgs>(args)...);
  53. // Append task to the list
  54. {
  55. LockGuard<Mutex> lock(m_mtx);
  56. if(m_tail != nullptr)
  57. {
  58. ANKI_ASSERT(m_tail->m_next == nullptr);
  59. ANKI_ASSERT(m_head != nullptr);
  60. m_tail->m_next = newTask;
  61. m_tail = newTask;
  62. }
  63. else
  64. {
  65. ANKI_ASSERT(m_head == nullptr);
  66. m_head = m_tail = newTask;
  67. }
  68. }
  69. // Wake up the thread
  70. m_condVar.notifyOne();
  71. }
  72. /// @}
  73. } // end namespace anki