| @@ -24,8 +24,11 @@ | |||
| #include <cstdlib> | |||
| #include <cstring> | |||
| // #define CPP11_MUTEX | |||
| #ifdef CPP11_MUTEX | |||
| # include <mutex> | |||
| # include <thread> | |||
| #else | |||
| # include <pthread.h> | |||
| #endif | |||
| @@ -314,6 +317,216 @@ private: | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex) | |||
| }; | |||
| // ------------------------------------------------- | |||
| // CarlaThread class | |||
| class CarlaThread | |||
| { | |||
| public: | |||
| CarlaThread() | |||
| : fStarted(false), | |||
| fFinished(false) | |||
| { | |||
| #ifdef CPP11_MUTEX | |||
| cthread = nullptr; | |||
| #else | |||
| _zero(); | |||
| pthread_attr_init(&pthreadAttr); | |||
| pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE); | |||
| #endif | |||
| } | |||
| ~CarlaThread() | |||
| { | |||
| CARLA_ASSERT(! isRunning()); | |||
| if (isRunning()) | |||
| terminate(); | |||
| #ifdef CPP11_MUTEX | |||
| if (cthread != nullptr) | |||
| { | |||
| cthread->join(); | |||
| delete cthread; | |||
| } | |||
| #else | |||
| if (pthreadId != 0) | |||
| pthread_join(pthreadId, nullptr); | |||
| pthread_attr_destroy(&pthreadAttr); | |||
| #endif | |||
| } | |||
| bool start() | |||
| { | |||
| CARLA_ASSERT(! isRunning()); | |||
| if (isRunning()) | |||
| return false; | |||
| fStarted = false; | |||
| fFinished = false; | |||
| #ifdef CPP11_MUTEX | |||
| CARLA_ASSERT(cthread == nullptr); | |||
| if (cthread != nullptr) | |||
| return false; | |||
| cthread = new std::thread(_cthreadRoutine, this); | |||
| CARLA_ASSERT(cthread->joinable()); | |||
| return true; | |||
| #else | |||
| CARLA_ASSERT(pthreadId == 0); | |||
| if (pthreadId != 0) | |||
| return false; | |||
| return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0); | |||
| #endif | |||
| } | |||
| bool stop(const unsigned int timeout = 0) | |||
| { | |||
| CARLA_ASSERT(isRunning()); | |||
| if (! isRunning()) | |||
| return true; | |||
| #ifdef CPP11_MUTEX | |||
| if (cthread == nullptr) | |||
| return true; | |||
| #else | |||
| if (pthreadId == 0) | |||
| return true; | |||
| #endif | |||
| if (timeout == 0) | |||
| { | |||
| #ifdef CPP11_MUTEX | |||
| cthread->join(); | |||
| #else | |||
| pthread_join(pthreadId, nullptr); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| for (unsigned int i=0; i < timeout && ! fFinished; i++) | |||
| carla_msleep(1); | |||
| } | |||
| if (! fFinished) | |||
| return false; | |||
| #ifdef CPP11_MUTEX | |||
| delete cthread; | |||
| cthread = nullptr; | |||
| #else | |||
| _zero(); | |||
| #endif | |||
| return true; | |||
| } | |||
| void terminate() | |||
| { | |||
| CARLA_ASSERT(isRunning()); | |||
| if (fFinished) | |||
| return; | |||
| #ifdef CPP11_MUTEX | |||
| if (cthread == nullptr) | |||
| return; | |||
| #else | |||
| if (pthreadId == 0) | |||
| return; | |||
| #endif | |||
| #ifdef CPP11_MUTEX | |||
| cthread->detach(); | |||
| //cthread->join(); | |||
| delete cthread; | |||
| cthread = nullptr; | |||
| #else | |||
| pthread_detach(pthreadId); | |||
| //pthread_join(pthreadId, nullptr); | |||
| pthread_cancel(pthreadId); | |||
| _zero(); | |||
| #endif | |||
| fFinished = true; | |||
| } | |||
| bool isRunning() | |||
| { | |||
| return (fStarted && ! fFinished); | |||
| } | |||
| void waitForStarted(const unsigned int timeout = 0) // ms | |||
| { | |||
| if (fStarted) | |||
| return; | |||
| if (timeout == 0) | |||
| { | |||
| while (! fStarted) {} | |||
| } | |||
| else | |||
| { | |||
| for (unsigned int i=0; i < timeout && ! fStarted; i++) | |||
| carla_msleep(1); | |||
| } | |||
| } | |||
| void waitForFinished() | |||
| { | |||
| waitForStarted(); | |||
| stop(0); | |||
| } | |||
| protected: | |||
| virtual void run() = 0; | |||
| private: | |||
| bool fStarted; | |||
| bool fFinished; | |||
| void handleRoutine() | |||
| { | |||
| fStarted = true; | |||
| run(); | |||
| fFinished = true; | |||
| } | |||
| #ifdef CPP11_MUTEX | |||
| std::thread* cthread; | |||
| static void _cthreadRoutine(CarlaThread* const _this_) | |||
| { | |||
| _this_->handleRoutine(); | |||
| } | |||
| #else | |||
| pthread_t pthreadId; | |||
| pthread_attr_t pthreadAttr; | |||
| static void* _pthreadRoutine(void* const _this_) | |||
| { | |||
| ((CarlaThread*)_this_)->handleRoutine(); | |||
| pthread_exit(nullptr); | |||
| } | |||
| void _zero() | |||
| { | |||
| carla_zeroStruct<pthread_t>(pthreadId); | |||
| } | |||
| #endif | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread) | |||
| }; | |||
| // ------------------------------------------------- | |||
| // CarlaString class | |||