Audio plugin host https://kx.studio/carla
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.

275 lines
5.3KB

  1. /*
  2. * Carla Thread
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. #ifndef __CARLA_THREAD_HPP__
  18. #define __CARLA_THREAD_HPP__
  19. #include "CarlaJuceUtils.hpp"
  20. #error This class is not ready for usage yet
  21. // #define CPP11_THREAD
  22. #ifdef CPP11_THREAD
  23. # include <thread>
  24. #else
  25. # include <pthread.h>
  26. #endif
  27. // -------------------------------------------------
  28. // CarlaThread class
  29. class CarlaThread
  30. {
  31. public:
  32. CarlaThread()
  33. : fStarted(false),
  34. fFinished(false)
  35. {
  36. #ifdef CPP11_THREAD
  37. cthread = nullptr;
  38. #else
  39. _zero();
  40. pthread_attr_init(&pthreadAttr);
  41. pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
  42. #endif
  43. }
  44. ~CarlaThread()
  45. {
  46. CARLA_ASSERT(! isRunning());
  47. if (isRunning())
  48. terminate();
  49. #ifdef CPP11_THREAD
  50. if (cthread != nullptr)
  51. {
  52. cthread->join();
  53. delete cthread;
  54. }
  55. #else
  56. //if (! _isNull())
  57. // pthread_join(pthreadId, nullptr);
  58. pthread_attr_destroy(&pthreadAttr);
  59. #endif
  60. }
  61. bool start()
  62. {
  63. CARLA_ASSERT(! isRunning());
  64. if (isRunning())
  65. return false;
  66. fStarted = false;
  67. fFinished = false;
  68. #ifdef CPP11_THREAD
  69. CARLA_ASSERT(cthread == nullptr);
  70. if (cthread != nullptr)
  71. return false;
  72. cthread = new std::thread(_cthreadRoutine, this);
  73. CARLA_ASSERT(cthread->joinable());
  74. return true;
  75. #else
  76. CARLA_ASSERT(_isNull());
  77. if (! _isNull())
  78. return false;
  79. return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0);
  80. #endif
  81. }
  82. bool stop(const unsigned int timeout = 0)
  83. {
  84. CARLA_ASSERT(isRunning());
  85. if (! isRunning())
  86. return true;
  87. #ifdef CPP11_THREAD
  88. if (cthread == nullptr)
  89. return true;
  90. #else
  91. if (_isNull())
  92. return true;
  93. #endif
  94. if (timeout == 0)
  95. {
  96. #ifdef CPP11_THREAD
  97. cthread->join();
  98. #else
  99. pthread_join(pthreadId, nullptr);
  100. #endif
  101. }
  102. else
  103. {
  104. for (unsigned int i=0; i < timeout && ! fFinished; i++)
  105. carla_msleep(1);
  106. }
  107. if (! fFinished)
  108. return false;
  109. #ifdef CPP11_THREAD
  110. delete cthread;
  111. cthread = nullptr;
  112. #else
  113. _zero();
  114. #endif
  115. return true;
  116. }
  117. void terminate()
  118. {
  119. CARLA_ASSERT(isRunning());
  120. if (fFinished)
  121. return;
  122. #ifdef CPP11_THREAD
  123. if (cthread == nullptr)
  124. return;
  125. #else
  126. if (_isNull())
  127. return;
  128. #endif
  129. #ifdef CPP11_THREAD
  130. cthread->detach();
  131. //cthread->join();
  132. delete cthread;
  133. cthread = nullptr;
  134. #else
  135. pthread_detach(pthreadId);
  136. //pthread_join(pthreadId, nullptr);
  137. pthread_cancel(pthreadId);
  138. _zero();
  139. #endif
  140. fFinished = true;
  141. }
  142. bool isRunning()
  143. {
  144. if (fStarted && ! fFinished)
  145. return true;
  146. // take the chance to clear data
  147. #ifdef CPP11_THREAD
  148. if (cthread != nullptr)
  149. {
  150. cthread->join();
  151. delete cthread;
  152. cthread = nullptr;
  153. }
  154. #else
  155. if (! _isNull())
  156. {
  157. //pthread_join(pthreadId, nullptr);
  158. //_zero();
  159. }
  160. #endif
  161. return false;
  162. }
  163. void waitForStarted(const unsigned int timeout = 0) // ms
  164. {
  165. if (fStarted)
  166. return;
  167. if (timeout == 0)
  168. {
  169. while (! fStarted)
  170. carla_msleep(1);
  171. }
  172. else
  173. {
  174. for (unsigned int i=0; i < timeout && ! fStarted; i++)
  175. carla_msleep(1);
  176. }
  177. }
  178. void waitForFinished()
  179. {
  180. waitForStarted();
  181. stop(0);
  182. }
  183. protected:
  184. virtual void run() = 0;
  185. private:
  186. bool fStarted;
  187. bool fFinished;
  188. void handleRoutine()
  189. {
  190. fStarted = true;
  191. run();
  192. fFinished = true;
  193. }
  194. #ifdef CPP11_THREAD
  195. std::thread* cthread;
  196. static void _cthreadRoutine(CarlaThread* const _this_)
  197. {
  198. _this_->handleRoutine();
  199. }
  200. #else
  201. pthread_t pthreadId;
  202. pthread_attr_t pthreadAttr;
  203. static void* _pthreadRoutine(void* const _this_)
  204. {
  205. ((CarlaThread*)_this_)->handleRoutine();
  206. pthread_exit(nullptr);
  207. return nullptr;
  208. }
  209. bool _isNull()
  210. {
  211. #ifdef CARLA_OS_WIN
  212. return (pthreadId.p == nullptr);
  213. #else
  214. return (pthreadId == 0);
  215. #endif
  216. }
  217. void _zero()
  218. {
  219. carla_zeroStruct<pthread_t>(pthreadId);
  220. }
  221. #endif
  222. //CARLA_PREVENT_HEAP_ALLOCATION
  223. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
  224. };
  225. // -------------------------------------------------
  226. #endif // __CARLA_THREAD_HPP__