AsyncLoader.h 1.8 KB

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