You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

133 lines
3.2 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // 2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the Do What The Fuck You Want To
  8. // Public License, Version 2, as published by Sam Hocevar. See
  9. // http://www.wtfpl.net/ for more details.
  10. //
  11. #if HAVE_CONFIG_H
  12. # include "config.h"
  13. #endif
  14. #include <lol/main.h>
  15. namespace lol
  16. {
  17. #if LOL_FEATURE_THREADS
  18. BaseThreadManager::BaseThreadManager(int thread_count)
  19. {
  20. m_thread_count = thread_count;
  21. }
  22. BaseThreadManager::~BaseThreadManager()
  23. {
  24. Stop();
  25. }
  26. //Initialize, Ticker::Ref and start the thread
  27. bool BaseThreadManager::Start()
  28. {
  29. if (m_threads.Count() > 0)
  30. return false;
  31. /* Spawn worker threads and wait for their readiness. */
  32. m_threads.Resize(m_thread_count);
  33. for (int i = 0; i < m_thread_count; i++)
  34. m_threads[i] = new Thread(BaseThreadWork, this);
  35. for (int i = 0; i < m_thread_count; i++)
  36. m_spawnqueue.Pop();
  37. return true;
  38. }
  39. //Stop the threads
  40. bool BaseThreadManager::Stop()
  41. {
  42. if (m_threads.Count() <= 0)
  43. return false;
  44. /* Signal worker threads for completion and wait for
  45. * them to quit. */
  46. ThreadJob stop_job(ThreadJobType::THREAD_STOP);
  47. for (int i = 0; i < m_thread_count; i++)
  48. m_jobqueue.Push(&stop_job);
  49. for (int i = 0; i < m_thread_count; i++)
  50. m_donequeue.Pop();
  51. return true;
  52. }
  53. //Work stuff
  54. bool BaseThreadManager::AddWork(ThreadJob* job)
  55. {
  56. if (m_jobqueue.TryPush(job))
  57. return true;
  58. return false;
  59. }
  60. bool BaseThreadManager::FetchResult(array<ThreadJob*>& results)
  61. {
  62. ThreadJob* result;
  63. while (m_resultqueue.TryPop(result))
  64. results << result;
  65. return results.Count() > 0;
  66. }
  67. //Base thread work function
  68. void *BaseThreadManager::BaseThreadWork(void* data)
  69. {
  70. BaseThreadManager *that = (BaseThreadManager *)data;
  71. that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED);
  72. for ( ; ; )
  73. {
  74. ThreadJob* job = that->m_jobqueue.Pop();
  75. if (job->GetJobType() == ThreadJobType::THREAD_STOP)
  76. break;
  77. else if (*job == ThreadJobType::WORK_TODO)
  78. {
  79. if (job->DoWork())
  80. job->SetJobType(ThreadJobType::WORK_DONE);
  81. else
  82. job->SetJobType(ThreadJobType::WORK_FAILED);
  83. that->m_resultqueue.Push(job);
  84. }
  85. }
  86. that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED);
  87. return nullptr;
  88. }
  89. void BaseThreadManager::TickGame(float seconds)
  90. {
  91. Entity::TickGame(seconds);
  92. //Start if needed
  93. Start();
  94. //Dispatch work task
  95. while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last()))
  96. m_job_dispatch.Pop();
  97. array<ThreadJob*> result;
  98. //Fetch and treat results
  99. if (FetchResult(result))
  100. {
  101. for (int i = 0; i < result.Count(); i++)
  102. {
  103. ThreadJob* job = result[i];
  104. if (job->GetJobType() == ThreadJobType::WORK_DONE)
  105. {
  106. job->SetJobType(ThreadJobType::WORK_FETCHED);
  107. TreatResult(job);
  108. }
  109. }
  110. }
  111. }
  112. #endif //LOL_FEATURE_THREADS
  113. } /* namespace lol */