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.

99 lines
2.2 KiB

  1. /* Copyright(C) 2019 MariaDB Corporation.
  2. This program is free software; you can redistribute itand /or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; version 2 of the License.
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License
  10. along with this program; if not, write to the Free Software
  11. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
  12. #include <tpool.h>
  13. #include <queue>
  14. #include <mutex>
  15. #include <condition_variable>
  16. #include <tpool_structs.h>
  17. #include <thread>
  18. #include <assert.h>
  19. #ifndef _WIN32
  20. #include <unistd.h> // usleep
  21. #endif
  22. namespace tpool
  23. {
  24. task_group::task_group(unsigned int max_concurrency) :
  25. m_queue(8),
  26. m_mtx(),
  27. m_tasks_running(),
  28. m_max_concurrent_tasks(max_concurrency)
  29. {};
  30. void task_group::set_max_tasks(unsigned int max_concurrency)
  31. {
  32. std::unique_lock<std::mutex> lk(m_mtx);
  33. m_max_concurrent_tasks = max_concurrency;
  34. }
  35. void task_group::execute(task* t)
  36. {
  37. std::unique_lock<std::mutex> lk(m_mtx);
  38. if (m_tasks_running == m_max_concurrent_tasks)
  39. {
  40. /* Queue for later execution by another thread.*/
  41. m_queue.push(t);
  42. return;
  43. }
  44. m_tasks_running++;
  45. for (;;)
  46. {
  47. lk.unlock();
  48. if (t)
  49. {
  50. t->m_func(t->m_arg);
  51. t->release();
  52. }
  53. lk.lock();
  54. if (m_queue.empty())
  55. break;
  56. t = m_queue.front();
  57. m_queue.pop();
  58. }
  59. m_tasks_running--;
  60. }
  61. void task_group::cancel_pending(task* t)
  62. {
  63. std::unique_lock<std::mutex> lk(m_mtx);
  64. if (!t)
  65. m_queue.clear();
  66. for (auto it = m_queue.begin(); it != m_queue.end(); it++)
  67. {
  68. if (*it == t)
  69. {
  70. (*it)->release();
  71. (*it) = nullptr;
  72. }
  73. }
  74. }
  75. task_group::~task_group()
  76. {
  77. std::unique_lock<std::mutex> lk(m_mtx);
  78. assert(m_queue.empty());
  79. while (m_tasks_running)
  80. {
  81. lk.unlock();
  82. #ifndef _WIN32
  83. usleep(1000);
  84. #else
  85. Sleep(1);
  86. #endif
  87. lk.lock();
  88. }
  89. }
  90. }