|
|
@@ -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 |
|
|
|
|
|
|
|