Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

129 righe
3.1 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. #include <lol/engine-internal.h>
  12. namespace lol
  13. {
  14. #if LOL_FEATURE_THREADS
  15. BaseThreadManager::BaseThreadManager(int thread_count)
  16. {
  17. m_thread_count = thread_count;
  18. }
  19. BaseThreadManager::~BaseThreadManager()
  20. {
  21. Stop();
  22. }
  23. //Initialize, Ticker::Ref and start the thread
  24. bool BaseThreadManager::Start()
  25. {
  26. if (m_threads.Count() > 0)
  27. return false;
  28. /* Spawn worker threads and wait for their readiness. */
  29. m_threads.Resize(m_thread_count);
  30. for (int i = 0; i < m_thread_count; i++)
  31. m_threads[i] = new Thread(BaseThreadWork, this);
  32. for (int i = 0; i < m_thread_count; i++)
  33. m_spawnqueue.Pop();
  34. return true;
  35. }
  36. //Stop the threads
  37. bool BaseThreadManager::Stop()
  38. {
  39. if (m_threads.Count() <= 0)
  40. return false;
  41. /* Signal worker threads for completion and wait for
  42. * them to quit. */
  43. ThreadJob stop_job(ThreadJobType::THREAD_STOP);
  44. for (int i = 0; i < m_thread_count; i++)
  45. m_jobqueue.Push(&stop_job);
  46. for (int i = 0; i < m_thread_count; i++)
  47. m_donequeue.Pop();
  48. return true;
  49. }
  50. //Work stuff
  51. bool BaseThreadManager::AddWork(ThreadJob* job)
  52. {
  53. if (m_jobqueue.TryPush(job))
  54. return true;
  55. return false;
  56. }
  57. bool BaseThreadManager::FetchResult(array<ThreadJob*>& results)
  58. {
  59. ThreadJob* result;
  60. while (m_resultqueue.TryPop(result))
  61. results << result;
  62. return results.Count() > 0;
  63. }
  64. //Base thread work function
  65. void *BaseThreadManager::BaseThreadWork(void* data)
  66. {
  67. BaseThreadManager *that = (BaseThreadManager *)data;
  68. that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED);
  69. for ( ; ; )
  70. {
  71. ThreadJob* job = that->m_jobqueue.Pop();
  72. if (job->GetJobType() == ThreadJobType::THREAD_STOP)
  73. break;
  74. else if (*job == ThreadJobType::WORK_TODO)
  75. {
  76. if (job->DoWork())
  77. job->SetJobType(ThreadJobType::WORK_DONE);
  78. else
  79. job->SetJobType(ThreadJobType::WORK_FAILED);
  80. that->m_resultqueue.Push(job);
  81. }
  82. }
  83. that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED);
  84. return nullptr;
  85. }
  86. void BaseThreadManager::TickGame(float seconds)
  87. {
  88. Entity::TickGame(seconds);
  89. //Start if needed
  90. Start();
  91. //Dispatch work task
  92. while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last()))
  93. m_job_dispatch.Pop();
  94. array<ThreadJob*> result;
  95. //Fetch and treat results
  96. if (FetchResult(result))
  97. {
  98. for (int i = 0; i < result.Count(); i++)
  99. {
  100. ThreadJob* job = result[i];
  101. if (job->GetJobType() == ThreadJobType::WORK_DONE)
  102. {
  103. job->SetJobType(ThreadJobType::WORK_FETCHED);
  104. TreatResult(job);
  105. }
  106. }
  107. }
  108. }
  109. #endif //LOL_FEATURE_THREADS
  110. } /* namespace lol */