| @@ -24,8 +24,11 @@ | |||||
| #include <cstdlib> | #include <cstdlib> | ||||
| #include <cstring> | #include <cstring> | ||||
| // #define CPP11_MUTEX | |||||
| #ifdef CPP11_MUTEX | #ifdef CPP11_MUTEX | ||||
| # include <mutex> | # include <mutex> | ||||
| # include <thread> | |||||
| #else | #else | ||||
| # include <pthread.h> | # include <pthread.h> | ||||
| #endif | #endif | ||||
| @@ -314,6 +317,216 @@ private: | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex) | 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 | // CarlaString class | ||||