AsyncLoader.h 1.7 KB

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